具有UITableView且具有动态标头作为单元格的自定义UICollectionView [英] Self-sizing UICollectionView with UITableView with dynamic header as a cell
问题描述
使用一个包含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屋!