UICollectionView动态标头大小

时间:2020-04-06 12:54:30

标签: ios swift uicollectionview uicollectionviewcell dynamic-type-feature

我有一个collectionView,其标题设计为.xib文件。它有一个简单的标签,它的文本支持dynamicType。

如何基于该标签和情节提要中的自动布局约束将标题的高度设置为动态?

到目前为止,我已经知道了:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    let kind = UICollectionView.elementKindSectionHeader
    let indexPath = IndexPath(row: 0, section: section)
    if let headerView = collectionView.supplementaryView(forElementKind: kind, at: indexPath) as? SectionHeaderView {
        headerView.layoutIfNeeded()
        headerView.setNeedsLayout()
        let size = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        return size
    }
    return CGSize(width: 0, height: 0)
}

但是它没有显示任何标题。

SectionHeaderView.xib看起来像这样: header.xib

CollectionView看起来像这样:您可以看到3个部分,但是看不到标题。 collectionView

如何使AutoLayout确定页眉的正确高度?

1 个答案:

答案 0 :(得分:2)

使用自定义流布局,通过Dynamic Type功能完美地管理集合视图中标题的高度。

标头元素被视为集合视图的补充元素,而referenceSizeForHeaderInSection'方法'仅用于初始化:Dynamic Type功能未调用。 ?

此后的解决方案基于自定义布局的layoutAttributesForElements方法,由于UIFontMetrics scaledValue,该方法将能够调整标题高度。

当用户更改字体大小时,由traitCollectionDidChange中调用的invalidateLayout方法触发的所有操作。 ?

STEP 1 ⟹创建一个简单的自定义标头类,例如:

class MyHeaderClass: UICollectionReusableView {

    override init(frame: CGRect) { super.init(frame: frame) }

    required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
}

STEP 2 ⟹创建一个新的空.xib,添加一个可重用的视图,并将其命名为与其所引用的类完全相同的名称:不要忘记在{{ 1}}。

STEP 3 ⟹在控制器中注册.xib文件:

Identity Inspector

STEP 4 ⟹支持数据源中的这个新单元格(标头是集合视图的补充元素)

collectionView.register(UINib(nibName: collectionViewHeaderFooterReuseIdentifier bundle: nil),
                        forSupplementaryViewOfKind: UICollectionElementKindSectionHeader,
                        withReuseIdentifier:collectionViewHeaderFooterReuseIdentifier)

...以及您的代表人(这会初始化标题大小并使其显示)

func collectionView(_ collectionView: UICollectionView,
                    viewForSupplementaryElementOfKind kind: String,
                    at indexPath: IndexPath) -> UICollectionReusableView {

    if (kind == UICollectionView.elementKindSectionHeader) {
        let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind,
                                                                         withReuseIdentifier: collectionViewHeaderReuseIdentifier,
                                                                         for: indexPath) as! MyHeader
        headerView.myLabel.text = "Your Header Title"
        return headerView
    } else {
        return UICollectionReusableView(frame: CGRect.null) }
}

..添加了全局func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize { return CGSize(width: collectionView.frame.width, height: headerHeight) } 进行初始化之后。

第5步⟹创建自定义流程布局,以使标题高度适应新的字体大小:

var headerHeight: CGFloat = 90.0

别忘了更新class FlowLayout: UICollectionViewFlowLayout { override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { let layoutAttributes = super.layoutAttributesForElements(in: rect) layoutAttributes?.forEach({ (attribute) in if (attribute.representedElementKind == UICollectionView.elementKindSectionHeader) { headerHeight = UIFontMetrics.default.scaledValue(for: 22.0) attribute.frame.size.height = headerHeight } }) return layoutAttributes } } 中的故事板: enter image description here 第6步⟹通知控制器,当用户更改字体大小时触发布局更新:

Interface Builder

按照此原理,将根据标题字体大小自动设置标题的正确高度。⟹我建议使用Xcode 11 new feature来测试override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { if (previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory) { collectionView?.collectionViewLayout.invalidateLayout() } } 很快。 ?

相关问题