【问题标题】:Swift: How to get correct UICollectionView height when using snapkit?Swift:使用 snapkit 时如何获得正确的 UICollectionView 高度?
【发布时间】:2017-05-22 13:15:06
【问题描述】:

我可能会以完全错误的方式处理此问题,因为我尝试做的事情应该很简单......我有一个包含几个子视图的视图组件,其中一个是 UICollectionView。我使用 SnapKit 布局子视图。 UICollectionView 是按钮的流布局,跨越 0-n 行,按钮的数量从一开始就知道。

当我通过 SnapKit 配置约束时,集合的高度为 0,因为不存在任何项目(仍然没有调用 cellForItemAt)。

如何在 SnapKit 中动态设置集合的高度?或者有没有更好的方法来获得我正在寻找的非常基本的流程布局(使用动态高度调整)?

(注意:代码有点简化,只显示相关部分)

class CategoryList: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {

    var categories : [String]?
    var buttons = [BorderedButton]()

    private(set) lazy var collectionView: UICollectionView = {
        var flowLayout = UICollectionViewFlowLayout()
        let collectionView = UICollectionView(frame: self.view.bounds, collectionViewLayout: flowLayout)
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "collectionCell")
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.backgroundColor = UIColor.cyan
        return collectionView
    }()

    override func loadView() {
        super.loadView()
        self.view.addSubview(collectionView)
    }

    override func viewDidLoad() {
        super.viewDidLoad()     
        setupConstraints()   
    }

    override func viewDidAppear(_ animated: Bool) {
        print("123: \(collectionView.contentSize.height)")
        //prints 47 for this particular example, however doing snp.makeConstraints
        //(or remakeConstraints) from here doesn't make any difference
        //setupConstraints()
    }

    func configure(categories:[String]) {
        self.categories = categories
        for category in categories {
            let button = BorderedButton()
            button.setTitle(category, for: .normal)
            buttons.append(button)
        }        
    }


    func collectionView(_ collectionView: UICollectionView,  numberOfItemsInSection section: Int) -> Int
    {
        return buttons.count
    }


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath)
        cell.addSubview(buttons[indexPath.row])

        //prints 47 for this particular example, however doing snp.makeConstraints
        //(or remakeConstraints) from here doesn't make any difference
        print("XYZ: \(collectionView.contentSize.height)")
        return cell
    }

    func collectionView(_ collectionView: UICollectionView,
                                 layout collectionViewLayout: UICollectionViewLayout,
                                 sizeForItemAt indexPath: IndexPath) -> CGSize
    {
        return buttons[indexPath.row].intrinsicContentSize
    }

    private func setupConstraints() {
        collectionView.snp.makeConstraints { (make) in
            make.left.top.equalToSuperview()
            make.width.equalTo(300)


            print("ABC: \(collectionView.contentSize.height)")

            //this does not work since height=0
            make.height.equalTo(collectionView.contentSize.height)

            //this works fine
            make.height.equalTo(47)
        }
    }

}  

谢谢!

编辑:添加缺少的类

感谢下面的回复。它确实有效,即使我错过了包含一半的代码,你也可以得到这个问题 :-) 下面是缺少的部分,它是使用 CategoryList 的类。在您的帮助下,我让 CategoryList 动态扩展到正确的高度,这非常好。但是,它会打乱周围视图(下面的 view1 和 view2)的位置。 我怀疑这与

有关

make.height.equalTo(categoryList.collectionView.snp.height)

行,也许它应该只引用 collectionView 约束属性,但我不知道应该(甚至可以)怎么做?

class PlaylistDetailsHeaderView : UITableViewCell {

    private var categoryList:CategoryList

    private(set) lazy var view1: UIView = {
        let view = UIView()
        return view
    }()

    private(set) lazy var view2: UIView = {
        let view = UIView()
        return view
    }()


    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {

        self.categoryList = CategoryList()

        super.init(style: style, reuseIdentifier: reuseIdentifier)

        self.contentView.addSubview(view1)
        self.contentView.addSubview(view2)
    }

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

    func configure() {

        let categories = ["alfa", "beta", "gamma", "fkdiii", "keoooe", "dfdsje", "jkjfldsjflsd", "alfa", "beta", "gamma", "fkdiii", "keoooe", "dfdsje", "jkjfldsjflsd"]

        categoryList.configure(categories: categories)
        self.contentView.addSubview(categoryList.view)

        setupConstraints()

    }

    private func setupConstraints() {

        view1.snp.makeConstraints { make in
            make.left.top.equalToSuperview()
        } 

        categoryList.view.snp.makeConstraints{ make in
            make.left.equalToSuperview()
            make.top.equalTo(view1.snp.bottom).offset(20)
            make.width.equalTo(300)

            make.height.equalTo(categoryList.collectionView.snp.height)   
        }

        view2.snp.makeConstraints { make in
            make.top.equalTo(categoryList.view.snp.bottom).offset(20)
        }
    }
}

【问题讨论】:

    标签: ios iphone swift uicollectionview snapkit


    【解决方案1】:

    如果我明白你的意思,我认为你应该这样做。

    首先,您需要将高度存储在某处。这将默认为 0,或者在您的情况下为 47。

    var heightConstraint: Constraint?
    

    然后您将像往常一样在 snapkit 中设置约束,但是当您设置高度约束时,您会将其存储在先前创建的变量中。不要忘记添加“.constraint”。

    heightConstraint = make.height.equalTo(47).constraint
    

    下一步是填充collectionView时,您可以再次使用heightConstraint(如果您使变量可达)

    heightConstraint.updateOffset(collectionView.contentSize.height)
    

    【讨论】:

    • 谢谢,这样会更好
    • 您理解我的意思并且您的解决方案有效。谢谢!虽然我错过了添加一些代码,所以我仍然很难让这个 100% 工作,希望你能再看看。
    • 我不完全确定这个,因为我从来没有做过这样的解决方案。但我同意这可能是你自己提到的。但我很确定您只是将collectionView.snp.height 存储在 categoryList 类中。我想你可以把它公开并从那里使用它吗? make.height.equalTo(categoryList.heightConstraint) 如果这不起作用,我不太确定如何解决问题。 (编辑有点像一个新问题)
    • 谢谢,没用,所以我按照你的建议发布了另一个。 stackoverflow.com/questions/44128955/…
    【解决方案2】:

    Vollan 的回答非常接近。只需确保您在更新约束时位于主线程上。所以总结一下:

    var collectionViewHeightConstraint: Constraint? // on top as class property 
    

    然后在 snapkit 块内:

    collectionView.snp.makeConstraints { make in
        make.top.equalToSuperview() //example
        collectionViewHeightConstraint = make.height.equalTo(self.collectionView.contentSize.height).constraint
    }
    

    最后但同样重要的是,当数据更新时,不要忘记:

    DispatchQueue.main.async {
        self.collectionViewHeightConstraint?.update(offset: self.collectionView.contentSize.height)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-11-27
      • 1970-01-01
      • 2015-08-16
      • 1970-01-01
      • 1970-01-01
      • 2017-04-11
      • 1970-01-01
      相关资源
      最近更新 更多