如何在 Swift 中以编程方式更改 UICollectionViewCell 大小?

How to change UICollectionViewCell size programmatically in Swift?

我有一个 UICollectionView 和一个 segmented control 可以在数据之间切换。但是如何以编程方式更改UICollectionViewCell大小属性?然后我可以为每种数据类型适当地自定义每种样式。

例如 将宽度更改为 520 点,将高度更改为 100。我是 iOS 开发的新手并且对 CSS 有经验:/

我知道如何在 Xcode 中执行此操作(显然),但不知道在 swift 中更改它的正确方法。非常感谢任何想法或反馈 (Y)

确保您的 class 符合 UICollectionViewDelegateFlowLayout (对于 swift4)

eg. class MyClass: UICollectionViewDelegateFlowLayout

之前 Swift 3

//Use for size
func collectionView(collectionView: UICollectionView,
        layout collectionViewLayout: UICollectionViewLayout,
        sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {

    }
//Use for interspacing
    func collectionView(collectionView: UICollectionView,
        layout collectionViewLayout: UICollectionViewLayout,
        minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
            return 1.0
    }

    func collectionView(collectionView: UICollectionView, layout
        collectionViewLayout: UICollectionViewLayout,
        minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
            return 1.0
    }

// 对于 swift 3

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    sizeForItemAt indexPath: IndexPath) -> CGSize {

}

func collectionView(_ collectionView: UICollectionView,
                    layout collectionViewLayout: UICollectionViewLayout,
                    minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

func collectionView(_ collectionView: UICollectionView, layout
    collectionViewLayout: UICollectionViewLayout,
                    minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 1.0
}

// 对于 swift 4

extension MyClass: UICollectionViewDelegateFlowLayout { 
        func collectionView(_ collectionView: UICollectionView,
                            layout collectionViewLayout: UICollectionViewLayout,
                            sizeForItemAt indexPath: IndexPath) -> CGSize {

        }

        func collectionView(_ collectionView: UICollectionView,
                            layout collectionViewLayout: UICollectionViewLayout,
                            minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
            return 1.0
        }

        func collectionView(_ collectionView: UICollectionView, layout
            collectionViewLayout: UICollectionViewLayout,
                            minimumLineSpacingForSectionAt section: Int) -> CGFloat {
            return 1.0
        }
    }

对 swift 3 使用与上面所示相同的代码,但只需 确保 你的 class 符合协议 UICollectionViewDelegateFlowLayout

Swift 3

来自@sumit-oberoi 回答的方法不会被调用 如果你正在使用Swift 3. 为了让它工作做这个调整:

  1. 遵守UICollectionViewDelegateFlowLayout协议。

  2. 实施这些方法:

    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {
    
    }
    
    func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 1.0
    }
    
    func collectionView(_ collectionView: UICollectionView, layout
        collectionViewLayout: UICollectionViewLayout,
                        minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 1.0
    }
    

注意变化:

  1. 在方法名collectionView前添加_
  2. NSIndexPath 更改为 IndexPath

Swift 3

override func viewDidLoad() {
    super.viewDidLoad()

    let cellSize = CGSize(width:80 , height:80)

    let layout = UICollectionViewFlowLayout()
    layout.scrollDirection = .vertical //.horizontal
    layout.itemSize = cellSize
    layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
    layout.minimumLineSpacing = 1.0
    layout.minimumInteritemSpacing = 1.0
    myCollectionView.setCollectionViewLayout(layout, animated: true)

    myCollectionView.reloadData()
}

如果您使用下面的 Gaurav Rami 代码

let cellSize = CGSize(width:80 , height:80)

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical //.horizontal
layout.itemSize = cellSize
layout.sectionInset = UIEdgeInsets(top: 1, left: 1, bottom: 1, right: 1)
layout.minimumLineSpacing = 1.0
layout.minimumInteritemSpacing = 1.0
myCollectionView.setCollectionViewLayout(layout, animated: true)

并收到此消息“对尚未呈现的视图进行快照会导致空快照。确保在屏幕更新后或快照之前至少呈现一次视图。" 你应该在为集合视图设置视图布局时删除动画

myCollectionView.setCollectionViewLayout(layout, animated: false)

然后消息就会消失

first Conform protocol the UICollectionViewDelegateFlowLayout

set width and height  UICollectionViewCell 

UIcollectionViewCell Hight = 300;
UIcollectionViewCell Width = 380;

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout,sizeForItemAt indexPath: IndexPath) -> CGSize {
      return CGSize(width: CGFloat((380)), height: CGFloat(300))
    }

尝试使用 UICollectionViewDelegateFlowLayout 方法。在 Xcode 11 或更高版本中,您需要从 Storyboard 中将 Estimate Size 设置为 none。

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: 
UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  let padding: CGFloat =  170
  let collectionViewSize = advertCollectionView.frame.size.width - padding
  return CGSize(width: collectionViewSize/2, height: collectionViewSize/2)
}

Swift 5:

  1. 遵守 UICollectionViewDelegateFlowLayout 协议,这意味着您需要将该协议放在 class 的继承中或作为扩展。像这样:

    class ViewController: UIViewController, UICollectionViewDelegate, 
    UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    }
    
  2. 实现 sizeForItemAt 方法:

    func collectionView(_ collectionView: UICollectionView, 布局 collectionViewLayout:UICollectionViewLayout,sizeForItemAt indexPath: IndexPath) -> CGSize { return CGSize(宽度: 100, 高度: 100) }

您可以在 CGSize 构造函数中输入您想要的宽度和高度。

  1. 在情节提要中 Select 集合视图并在大小检查器中将 估计大小 属性 设置为 NONE 如下所示:

  1. 在视图控制器中为视图控制器添加 UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let itemsPerRow:CGFloat = 2
    let padding:CGFloat = 20
    let itemWidth = (collectionView.bounds.width / itemsPerRow) - padding:CGFloat
    let itemHeight = collectionView.bounds.height - (2 * padding:CGFloat)
    return CGSize(width: itemWidth, height: itemHeight)
}
     /// this method is used for flow layout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let numberOfItemsPerRow:CGFloat = 3
    let spacingBetweenCells:CGFloat = 2

    // 2 is the value of sectionInset value
    
    let totalSpacing = (2 * 2) + ((numberOfItemsPerRow - 1) * spacingBetweenCells) //Amount of total spacing in a row
    if let collection = self.collectionAccounts{
        let width = (collection.bounds.width - totalSpacing)/numberOfItemsPerRow
        
        return CGSize(width: width, height: width)
    }else{
        return CGSize(width: 0, height: 0)
    }
}