简体   繁体   English

Swift UICollectionView单元格宽度

[英]Swift UICollectionView cell width

I'm trying to build a collection view without using interface builder, but I haven't been able to adjust the width of the cells. 我试图在不使用界面生成器的情况下构建集合视图,但无法调整单元格的宽度。 The cells appear to stay at their minimum square size, where I'd like the cells to stretch the width of the view. 单元格似乎保持在最小的正方形大小,我希望这些单元格可以拉伸视图的宽度。

What am I getting wrong with the constraints? 我对约束有什么误解?

Specifically: 特别:

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

Doesn't seem to be adjusting the width or height for the cells, full example: 似乎没有在调整单元格的宽度或高度,完整示例:

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)
    }
}

In terms of what's wrong with the constraints, you're missing the vertical constraints: 关于约束的问题,您缺少垂直约束:

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)
}

But that's not why your cells are the wrong size. 但这不是为什么细胞大小不正确的原因。 That's because your sizeForItemAt will not be called because you haven't declared UICollectionViewDelegateFlowLayout conformance. 这是因为你的sizeForItemAt不会被调用,因为你还没有宣布UICollectionViewDelegateFlowLayout一致性。 Set a breakpoint where you have it now, and you'll see it's not called. 在现在有断点的地方设置一个断点,您会看到它没有被调用。 You can fix this by moving it into an extension where you define the conformance: 您可以通过将其移动到定义一致性的扩展中来解决此问题:

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

Or, better, since they're all the same, I'd just set itemSize for the whole layout: 或者,更好的是,因为它们都相同,所以我只itemSize为整个布局设置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)
}

What am I getting wrong with the constraints? 我对约束有什么误解?

Nothing. 没有。 The width of a UICollectionViewCell under a UICollectionViewFlowLayout has nothing to do with its internal constraints. UICollectionViewFlowLayout下的UICollectionViewCell的宽度与其内部约束无关。 (There is supposed to be a feature that allows this, but it has never worked for me.) (应该有一个允许使用此功能的功能,但它对我从未有用。)

It is up to you to set the width explicitly, either by setting the flow layout's itemSize or by implementing collectionView(_:layout:sizeForItemAt:) in the collection view's delegate (which is usually a UICollectionViewController, and in any case must also explicitly adopt UICollectionViewDelegateFlowLayout as you've been told in Rob's answer). 您可以通过设置流程布局的itemSize或在集合视图的委托(通常是UICollectionViewController)中实现collectionView(_:layout:sizeForItemAt:)来显式设置宽度,并且在任何情况下还必须显式地采用宽度如Rob的回答所述,UICollectionViewDelegateFlowLayout)。

So just change this: 因此,只需更改此:

class UserCollectionViewController: UICollectionViewController {

to this: 对此:

class UserCollectionViewController : UICollectionViewController, UICollectionViewDelegateFlowLayout {

and you're done. 到此为止。

Create an extension on UIView and add this code: 在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))

    }
}

Then Create a custom class for your collectionViewCell and add this code: 然后为您的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
    }

Call this code in override func setUpViews() {} override func setUpViews() {}调用此代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM