【问题标题】:UICollectionView dynamic header sizeUICollectionView 动态标题大小
【发布时间】:2020-07-18 11:36:12
【问题描述】:

我有一个在 .xib 文件中设计的带有标题的 collectionView。它有一个简单的标签,它的文本支持动态类型。

如何根据该标签和 Storyboard 中的自动布局约束将该标题的高度设置为动态?

到目前为止,我得到了这个:

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 如下所示:

CollectionView 如下所示:您看到 3 个部分,但没有看到标题。

如何让 AutoLayout 确定标题的正确高度?

【问题讨论】:

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


    【解决方案1】:

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

    标题元素被视为集合视图的补充元素referenceSizeForHeaderInSection“方法”仅用于初始化:它不使用Dynamic Type 功能调用。 ?

    下面的解决方案基于自定义布局的layoutAttributesForElements 方法,由于UIFontMetrics scaledValue 将能够适应标题高度。

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

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

    class MyHeaderClass: UICollectionReusableView {
    
        override init(frame: CGRect) { super.init(frame: frame) }
    
        required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }
    }
    

    第 2 步 ⟹ 创建一个新的空 .xib,添加一个可重用的视图,并将其命名为与其引用的类完全相同的名称:不要忘记在 @987654335 中更改其类名@。

    第三步 ⟹在控制器中注册.xib文件:

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

    第 4 步 ⟹ 在您的数据源中支持这个新单元格(标题是集合视图的补充元素)

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

    .. 添加全局var headerHeight: CGFloat = 90.0 进行初始化后。

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

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

    别忘了更新Interface Builder 中的情节提要: STEP 6 ⟹ 当用户改变字体大小时,通知控制器触发布局更新:

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        if (previousTraitCollection?.preferredContentSizeCategory != traitCollection.preferredContentSizeCategory) {
            collectionView?.collectionViewLayout.invalidateLayout()
        }
    }
    

    根据这个原理,根据标题字体大小自动设置正确的标题高度 ⟹我建议使用Xcode 11 new feature快速测试Dynamic Type。 ?

    【讨论】:

    • 我遵循了一切,但对我没有用。
    猜你喜欢
    • 1970-01-01
    • 2014-10-27
    • 1970-01-01
    • 2019-03-26
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    相关资源
    最近更新 更多