具有UITableView且具有动态标头作为单元格的自定义UICollectionView [英] Self-sizing UICollectionView with UITableView with dynamic header as a cell

查看:60
本文介绍了具有UITableView且具有动态标头作为单元格的自定义UICollectionView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用一个包含UITableView的单元格制作一个自定尺寸的UICollectionView时遇到问题,该单元格的标头具有动态高度的标签.

I have a problem with making a self sizing UICollectionView with a cell that contains UITableView with a header that has a label with dynamic height.

有人可以指出我在所附示例项目中需要更改的内容吗?

Can someone point me out to what I need to change in the attached sample project?

您可以在屏幕截图上看到该表格不适合该视图,因为当前手动设置了单元格的高度.

You can see on the screenshot that the table does not fit the view as the cell's height is currently manually set.

import UIKit

class ViewController: UIViewController {
    static let section1 = "section1"
        static let section2 = "section2"
        private weak var collectionView: UICollectionView!

        override func viewDidLoad() {
            self.navigationItem.title = "Collection View"
            super.viewDidLoad()
            self.setupCollectionView()
        }

        private func setupCollectionView() {
            let flowLayout = UICollectionViewFlowLayout()
            flowLayout.scrollDirection = .vertical
            flowLayout.minimumInteritemSpacing = 0.0
            flowLayout.minimumLineSpacing = 0.0
            let collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: flowLayout)
            collectionView.alwaysBounceVertical = true
            collectionView.register(
                SectionHeaderView.self,
                forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
                withReuseIdentifier: SectionHeaderView.sectionHeaderId
            )
            collectionView.register(Section1.self, forCellWithReuseIdentifier: ViewController.section1)
            collectionView.register(Section2.self, forCellWithReuseIdentifier: ViewController.section2)
            self.view.addSubview(collectionView)
            self.collectionView = collectionView
            self.collectionView.translatesAutoresizingMaskIntoConstraints = false
            self.collectionView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
            self.collectionView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
            self.collectionView.leftAnchor.constraint(equalTo: self.view.leftAnchor).isActive = true
            self.collectionView.rightAnchor.constraint(equalTo: self.view.rightAnchor).isActive = true
            self.collectionView.dataSource = self
            self.collectionView.delegate = self
        }
    }

    // MARK: - UICollectionViewDelegateFlowLayout
    extension ViewController: UICollectionViewDelegateFlowLayout {
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            switch indexPath.section {
            case 0:
                return CGSize(width: self.view.frame.width, height: 210.0)
            case 1:
                return CGSize(width: self.view.frame.width, height: 5 * 51.0 + 130.0) // How to enable self-sizing cells for table view inside
            default:
                fatalError("Unsupported section index.")
            }
        }

        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
            return CGSize(width: self.view.frame.width, height: 61)
        }
    }

    // MARK: - UICollectionViewDataSource
    extension ViewController: UICollectionViewDataSource {
        func numberOfSections(in collectionView: UICollectionView) -> Int {
            return 2
        }

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

        func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
            let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: SectionHeaderView.sectionHeaderId, for: indexPath) as! SectionHeaderView
            switch indexPath.section {
            case 0:
                header.uiLabel.text = "Section 1"
            case 1:
                header.uiLabel.text = "Section 2"
            default:
                fatalError("Unsupported section index.")
            }
            return header
        }

        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            switch indexPath.section {
            case 0:
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ViewController.section1, for: indexPath) as! Section1
                return cell
            case 1:
                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ViewController.section2, for: indexPath) as! Section2
                return cell
            default:
                fatalError("OverviewController: Unsupported section index.")
            }
        }
}

推荐答案

要实现自动调整collectionView单元的大小,您实际上只需要进行一些更改.

To implement auto-sizing collectionView cells, you really only need a few changes.

夫妇要点:

  • 单元必须满足其自身的约束.因此,确保在单元格中具有宽度和高度约束,而不是在sizeForItemAt中计算大小.这些可以基于内容是动态的.

  • Cells must satisfy their own constraints. So, instead of calculating sizing in sizeForItemAt, make sure the cells have width and height constraints. These can be dynamic, based on content.

将元素添加到集合视图单元格的contentView,而不是单元格本身.

Add elements to the collection view cell's contentView, not to the cell itself.

对于嵌入式非滚动表视图,请使用一个子类,该子类根据表的contentSize设置内部内容大小的高度.示例:

For the embedded non-scrolling table view, use a subclass that sets the intrinsic content size height based on the table's contentSize. Example:

final class ContentSizedTableView: UITableView {
    override var contentSize:CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }
    override var intrinsicContentSize: CGSize {
        layoutIfNeeded()
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    }
}


这里有一个很好的教程(不是我的): https://medium.com/@andrea.toso/uicollectionviewcell-dynamic-height-swift-b099b28ddd23 ,其中有更详细的说明.


There is a pretty good tutorial here (not mine): https://medium.com/@andrea.toso/uicollectionviewcell-dynamic-height-swift-b099b28ddd23 that has more detailed explanations.

我在您提供的项目中实现了这些概念,并将其放在GitHub存储库上(以方便查看更改): https://github.com/DonMag/ThunderCollectionView

I implement those concepts in the project you made available, and put it up on a GitHub repo (to make it easy to see the changes): https://github.com/DonMag/ThunderCollectionView

结果:

这篇关于具有UITableView且具有动态标头作为单元格的自定义UICollectionView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆