Swift UICollectionView单元格宽度

时间:2018-03-18 19:28:33

标签: ios swift uicollectionview constraints

我试图在不使用界面构建器的情况下构建集合视图,但我还没有能够调整单元格的宽度。细胞似乎保持在最小的方形尺寸,我希望细胞伸展视图的宽度。

我对约束的错误是什么?

具体做法是:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: view.frame.width, height: 50)
}

似乎没有调整单元格的宽度或高度,完整示例:

import UIKit

class UserCollectionViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationItem.title = "foo"
        collectionView?.backgroundColor = UIColor.red
        collectionView?.alwaysBounceVertical = true
        collectionView?.register(UserCell.self, forCellWithReuseIdentifier: "cellId")
    }

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 20
    }

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let userCell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath)
        return userCell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height: 50)
    }
}

class UserCell:UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    let nameLabel: UILabel = {
        let label = UILabel()
        label.text = "foo"
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = UIFont.boldSystemFont(ofSize: 14)
        return label
    }()

    func setupView() {
        addSubview(nameLabel)
        let hConstraints = NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": nameLabel])
        addConstraints(hConstraints)
    }
}

3 个答案:

答案 0 :(得分:1)

就约束的错误而言,你错过了纵向约束:

func setupView() {
    addSubview(nameLabel)

    var constraints: [NSLayoutConstraint] = []
    constraints += NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", metrics: nil, views: ["v0": nameLabel])
    constraints += NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", metrics: nil, views: ["v0": nameLabel])
    addConstraints(constraints)
}

但这不是你的细胞大小错误的原因。这是因为您的sizeForItemAt将不会被调用,因为您尚未声明UICollectionViewDelegateFlowLayout一致性。设置一个你现在拥有的断点,你会发现它没有被调用。您可以通过将其移动到定义一致性的扩展中来解决此问题:

extension UserCollectionViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.bounds.width, height: 50)
    }
}

或者,更好的是,由于它们完全一样,我只需为整个布局设置itemSize

override func viewDidLoad() {
    super.viewDidLoad()

    let layout = collectionView!.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: view.bounds.width, height: 50)
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)

    let layout = self.collectionView!.collectionViewLayout as! UICollectionViewFlowLayout
    layout.itemSize = CGSize(width: size.width, height: 50)
}

答案 1 :(得分:1)

  

我对约束的错误是什么?

无。 UICollectionViewFlowLayout下的UICollectionViewCell的宽度与其内部约束无关。 (应该有一个功能允许这个,但它从来没有对我有用。)

您可以通过设置流布局的itemSize或在集合视图的委托中实现collectionView(_:layout:sizeForItemAt:)来明确设置宽度(通常是UICollectionViewController,并且无论如何必须也正如你在Rob的回答中所说的那样明确地采用了UICollectionViewDelegateFlowLayout。

所以只需改变一下:

class UserCollectionViewController: UICollectionViewController {

到此:

class UserCollectionViewController : UICollectionViewController, UICollectionViewDelegateFlowLayout {

你已经完成了。

答案 2 :(得分:0)

在UIView上创建扩展并添加以下代码:

extension UIView {

    func addConstraintsWithformat(format: String, views: UIView...) {
        // abstracting contstraints code
        var viewsDict = [String: UIView]()
        for(index,view) in views.enumerated() {
            let key = "v\(index)"
            viewsDict[key] = view
            view.translatesAutoresizingMaskIntoConstraints = false
        }
        addConstraints(NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(), metrics: nil, views: viewsDict))

    }
}

然后为collectionViewCell创建自定义类并添加以下代码:

    private func setUpContainerView() {
        let containerView = UIView()
        addSubview(containerView)
        addConstraintsWithformat(format: "H:|-90-[v0]|", views: containerView)
        addConstraintsWithformat(format: "V:[v0(50)]|", views: containerView)
        addConstraint(NSLayoutConstraint(item: containerView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0))

        // set up labels and contents inside the ContainerView and set their constraints with addConstraintsWithformat
    }

override func setUpViews() {}

中调用此代码