Swift 如何在Ios中为UICollectionView设置自定义布局

Swift 如何在Ios中为UICollectionView设置自定义布局,swift,Swift,我知道如何在UICollectionView中显示集合单元格。但我想使用自定义布局来显示单元格 我的收藏应该有两列,其中单元格的宽度是固定的,但单元格的高度可能因标签的内容大小而异 但我不知道怎么做。 我想显示单元格集合,如下图所示 我想用swift实现它。使用此功能,您可以根据需要更改单元格的高度和宽度 func collectionView(collectionView:UICollectionView,布局collectionViewLayout:UICollectionViewLayo

我知道如何在UICollectionView中显示集合单元格。但我想使用自定义布局来显示单元格

我的收藏应该有两列,其中单元格的宽度是固定的,但单元格的高度可能因标签的内容大小而异

但我不知道怎么做。 我想显示单元格集合,如下图所示


我想用swift实现它。

使用此功能,您可以根据需要更改单元格的高度和宽度

func collectionView(collectionView:UICollectionView,布局collectionViewLayout:UICollectionViewLayout,SizeFormiteIndeXPath indexPath:indexPath)->CGSize{}


使用indexPath访问单元格

使用此函数可以根据需要更改单元格的高度和宽度

func collectionView(collectionView:UICollectionView,布局collectionViewLayout:UICollectionViewLayout,SizeFormiteIndeXPath indexPath:indexPath)->CGSize{}

使用indexPath访问单元格

  • 自定义UICollectionViewLayout类
  • 为视图控制器定义协议以计算每个单元格的高度
  • 将视图控制器设置为代理
  • 在委托方法中,需要计算每个单元格的动态高度
  • 重写prepare函数,该函数将为每个单元格的高度调用委托方法,并在布局子类中为每个单元格生成自定义UICollectionViewLayoutAttributes实例
  • 您可能还需要将这些UICollectionViewLayoutAttribute实例存储在数组中,以获得更好的性能,从而避免重新计算。 (此步骤仅在禁用UICollectionView预取时有用。)
  • 重写layoutAttributesForElements函数以返回给定矩形内所有项的布局属性
  • 在自定义的UICollectionViewCell中应用这些UICollectionViewLayoutAttribute实例,以便执行一些自动布局
  • 重写UICollectionViewLayoutAttribute子类中的copy和isEqual函数。UICollectionViewLayoutAttribute的子类需要符合NSCopying协议,因为属性的对象可以在内部复制。必须实现isEqual来比较子类的自定义属性,例如标签的高度
  • 自定义UICollectionViewLayout类
  • 为视图控制器定义协议以计算每个单元格的高度
  • 将视图控制器设置为代理
  • 在委托方法中,需要计算每个单元格的动态高度
  • 重写prepare函数,该函数将为每个单元格的高度调用委托方法,并在布局子类中为每个单元格生成自定义UICollectionViewLayoutAttributes实例
  • 您可能还需要将这些UICollectionViewLayoutAttribute实例存储在数组中,以获得更好的性能,从而避免重新计算。 (此步骤仅在禁用UICollectionView预取时有用。)
  • 重写layoutAttributesForElements函数以返回给定矩形内所有项的布局属性
  • 在自定义的UICollectionViewCell中应用这些UICollectionViewLayoutAttribute实例,以便执行一些自动布局
  • 重写UICollectionViewLayoutAttribute子类中的copy和isEqual函数。UICollectionViewLayoutAttribute的子类需要符合NSCopying协议,因为属性的对象可以在内部复制。必须实现isEqual来比较子类的自定义属性,例如标签的高度

  • 以下是自定义布局的代码。在此布局中,单元格宽度为集合视图的一半,高度为每个单元格的特定高度。要设置每个单元格的高度,必须实现“func heightFor(index:Int)->CGFloat”。 要实现此布局,请执行以下步骤

  • 创建以下协议:

    //This protocol has to be confirmed in your controller.
    
      protocol CustomLayoutDelegate {
          //This method accept the height for your cell.
          func heightFor(index : Int) -> CGFloat
       }
    
  • 创建子类“UICollectionViewFlowLayout”:

  • 现在在你的xib上, 添加集合视图并连接到

    @iBolate弱var collectionView:UICollectionView

    并将“CustomLayout”类指定给集合的布局:

  • 现在,在运行项目之后,您将看到以下输出。确保集合视图单元格具有不同的颜色,仅用于标识


    以下是自定义布局的代码。在此布局中,单元格宽度为集合视图的一半,高度为每个单元格的特定高度。要设置每个单元格的高度,必须实现“func heightFor(index:Int)->CGFloat”。 要实现此布局,请执行以下步骤

  • 创建以下协议:

    //This protocol has to be confirmed in your controller.
    
      protocol CustomLayoutDelegate {
          //This method accept the height for your cell.
          func heightFor(index : Int) -> CGFloat
       }
    
  • 创建子类“UICollectionViewFlowLayout”:

  • 现在在你的xib上, 添加集合视图并连接到

    @iBolate弱var collectionView:UICollectionView

    并将“CustomLayout”类指定给集合的布局:

  • 现在,在运行项目之后,您将看到以下输出。确保集合视图单元格具有不同的颜色,仅用于标识


    谢谢,我按照您提到的那样做了,看起来像我期望的那样,但现在的问题是,当我要删除特定单元格(删除特定数组元素并重新加载collectionView)时,应用程序就会崩溃。它会显示类似“UICollectionView接收到索引路径不存在的单元格的布局属性”这样的错误:{length=2,path=0-4}'我一直在用这种方法编写我的应用程序。删除任何单元格后,应用程序不会崩溃。也许你可以禁用使用属性缓存数组进行测试。谢谢,我按照你提到的做了,看起来像我期望的,但现在的问题是,当我要删除特定单元格时(删除特定数组元素并重新加载collectionView)然后应用程序崩溃
    @IBOutlet weak var collectionView: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        //Register the cell for collection view
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
    
        //Assign the delegate
        if let layout = collectionView.collectionViewLayout as? CustomLayout{
            layout.layoutDelegate = self
        }
    }
    
    //CustomLayoutDelegate method
    func heightFor(index: Int) -> CGFloat {
    
        //Implement your own logic to return the height for specific cell
        return CGFloat(max(1, index) * 50)
    }
    
    // UICollectionViewDataSource methods
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 10
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
        cell.backgroundColor = UIColor.red
        return cell
    }
    }