Swift - UICollectionView

本文详细介绍如何在iOS应用中使用UICollectionView并实现自定义布局。通过创建UICollectionViewFlowLayout和CustomLayout类,可以调整cell尺寸、滑动方向及自定义cell位置和大小。示例代码展示了如何注册cell,加载图片和课程信息,并在不同位置显示不同大小的cell。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

import UIKit

class ViewController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegate {
    var images = ["image1","image2","image3","image4","image5","image6"]
    override func viewDidLoad() {
        super.viewDidLoad()
        //创建布局模式对象
        let flowLayout = UICollectionViewFlowLayout()
        //设置cell尺寸
        flowLayout.itemSize = CGSize(width: 155, height: 135)
        //设置滑动方向
        flowLayout.scrollDirection = UICollectionView.ScrollDirection.vertical
        //创建UICollectView对象
        let collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: flowLayout)
        
        collectionView.delegate = self
        collectionView.dataSource = self
        //创建重用cell(集合对象是代码生成的而不是NIB或故事板生成的因此需要注册一个UICollectionCell,否则初始化时会发生错误)
        collectionView.register(UICollectionViewCell.classForCoder(), forCellWithReuseIdentifier: "ReusedCell")
        self.view.addSubview(collectionView)
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return images.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let id = "ReusedCell"
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: id, for: indexPath)
        //检查cell中是否有tag为1的ImageView,没有创建一个
        let imageView:UIImageView? = (cell.viewWithTag(1) as? UIImageView)
        if imageView == nil{
            let image = UIImage(named: images[indexPath.row])
            let imageView = UIImageView(image: image)
            imageView.frame = CGRect(x: 0, y: 0, width: 150, height: 135)
            imageView.tag = 1
            cell.addSubview(imageView)
        }else{
            imageView?.image = UIImage(named: images[indexPath.row])
        }
        return cell
    }
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        collectionView.deselectItem(at: indexPath, animated: true)
    }
    
}

实现自定义布局

创建一个名为CustomLayout文件
CusyomLayout:

import UIKit

/**
 * 这个类只简单定义了一个section的布局
 */
class CustomLayout : UICollectionViewLayout {
    
    // 内容区域总大小,不是可见区域
    override var collectionViewContentSize: CGSize {
        let width = collectionView!.bounds.size.width - collectionView!.contentInset.left
            - collectionView!.contentInset.right
        let height = CGFloat((collectionView!.numberOfItems(inSection: 0) + 1) / 3)
        return CGSize(width: width, height: height)
    }
    
    // 所有单元格位置属性
    override func layoutAttributesForElements(in rect: CGRect)
        -> [UICollectionViewLayoutAttributes]? {
            var attributesArray = [UICollectionViewLayoutAttributes]()
            let cellCount = self.collectionView!.numberOfItems(inSection: 0)
            for i in 0..<cellCount {
                let indexPath =  IndexPath(item:i, section:0)
                let attributes =  self.layoutAttributesForItem(at: indexPath)
                attributesArray.append(attributes!)
            }
            return attributesArray
    }
    
    // 这个方法返回每个单元格的位置和大小
    override func layoutAttributesForItem(at indexPath: IndexPath)
        -> UICollectionViewLayoutAttributes? {
            //当前单元格布局属性
            let attribute =  UICollectionViewLayoutAttributes(forCellWith:indexPath)
            
            //单元格边长
            let largeCellSide = collectionViewContentSize.width / 3 * 2
            let smallCellSide = collectionViewContentSize.width / 3
            
            //当前行数,每行显示3个图片,1大2小
            let line:Int =  indexPath.item / 3
            //当前行的Y坐标
            let lineOriginY =  largeCellSide * CGFloat(line)
            //右侧单元格X坐标
            let rightLargeX = collectionViewContentSize.width - largeCellSide
            let rightSmallX = collectionViewContentSize.width - smallCellSide
            
            // 每行3个图片,2行循环一次,一共6种位置
            if (indexPath.item % 6 == 0) {
                attribute.frame = CGRect(x:0, y:lineOriginY, width:largeCellSide,
                                         height:largeCellSide)
            } else if (indexPath.item % 6 == 1) {
                attribute.frame = CGRect(x:rightSmallX, y:lineOriginY, width:smallCellSide,
                                         height:smallCellSide)
            } else if (indexPath.item % 6 == 2) {
                attribute.frame = CGRect(x:rightSmallX,
                                         y:lineOriginY + smallCellSide,
                                         width:smallCellSide, height:smallCellSide)
            } else if (indexPath.item % 6 == 3) {
                attribute.frame = CGRect(x:0, y:lineOriginY, width:smallCellSide,
                                         height:smallCellSide )
            } else if (indexPath.item % 6 == 4) {
                attribute.frame = CGRect(x:0,
                                         y:lineOriginY + smallCellSide,
                                         width:smallCellSide, height:smallCellSide)
            } else if (indexPath.item % 6 == 5) {
                attribute.frame = CGRect(x:rightLargeX, y:lineOriginY,
                                         width:largeCellSide,
                                         height:largeCellSide)
            }
            
            return attribute
    }
    
    /*
     //如果有页眉、页脚或者背景,可以用下面的方法实现更多效果
     func layoutAttributesForSupplementaryViewOfKind(elementKind: String!,
     atIndexPath indexPath: NSIndexPath!) -> UICollectionViewLayoutAttributes!
     func layoutAttributesForDecorationViewOfKind(elementKind: String!,
     atIndexPath indexPath: NSIndexPath!) -> UICollectionViewLayoutAttributes!
     */
}

ViewController:

import UIKit

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource
{
    var collectionView:UICollectionView!
    //课程名称和图片,每一门课程用字典来表示
    let courses = [
        ["name":"Swift","pic":"swift.png"],
        ["name":"Xcode","pic":"xcode.png"],
        ["name":"Java","pic":"java.png"],
        ["name":"PHP","pic":"php.png"],
        ["name":"JS","pic":"js.png"],
        ["name":"React","pic":"react.png"],
        ["name":"Ruby","pic":"ruby.png"],
        ["name":"HTML","pic":"html.png"],
        ["name":"C#","pic":"c#.png"]
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let layout = CustomLayout()
        //let layout = UICollectionViewFlowLayout()
        let frame = CGRect(x:0, y:20, width: view.bounds.size.width,
                           height:view.bounds.height-20)
        self.collectionView = UICollectionView(frame: frame, collectionViewLayout:layout)
        self.collectionView.delegate = self
        self.collectionView.dataSource = self
        // 注册CollectionViewCell
        self.collectionView.register(UICollectionViewCell.self,
                                     forCellWithReuseIdentifier: "ViewCell")
        //默认背景是黑色和label一致
        self.collectionView.backgroundColor = UIColor.white
        
        //设置collectionView的内边距
        self.collectionView.contentInset = UIEdgeInsetsMake(0, 5, 0, 5)
        
        self.view.addSubview(collectionView)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
    
    // CollectionView行数
    func collectionView(_ collectionView: UICollectionView,
                        numberOfItemsInSection section: Int) -> Int {
        return courses.count;
    }
    
    // 获取单元格
    func collectionView(_ collectionView: UICollectionView,
                        cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        // storyboard里设计的单元格
        let identify:String = "ViewCell"
        // 获取设计的单元格,不需要再动态添加界面元素
        let cell = self.collectionView.dequeueReusableCell(
            withReuseIdentifier: identify, for: indexPath) as UICollectionViewCell
        //先清空内部原有的元素
        for subview in cell.subviews {
            subview.removeFromSuperview()
        }
        // 添加图片
        let img = UIImageView(image: UIImage(named: courses[indexPath.row]["pic"]!))
        print(indexPath.item)
        img.frame = cell.bounds
        img.contentMode = .scaleAspectFit
        // 图片上面显示课程名称,居中显示
        let lbl = UILabel(frame:CGRect(x:0, y:0, width:cell.bounds.size.width, height:20))
        lbl.textColor = UIColor.white
        lbl.textAlignment = .center
        lbl.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.2)
        lbl.text = courses[indexPath.item]["name"]
        cell.addSubview(img)
        cell.addSubview(lbl)
        return cell
    }
    
    /* 自定义布局不需要调用
     //单元格大小
     func collectionView(collectionView: UICollectionView!,
     layout collectionViewLayout: UICollectionViewLayout!,
     sizeForItemAtIndexPath indexPath: NSIndexPath!) -> CGSize {
     let size:Float = indexPath.item % 3 == 0 ? 200 : 100
     return CGSize(width:size, height:size)
     }
     */
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值