具有可读内容宽度的UICollectionViewController流布局

时间:2017-08-07 17:12:39

标签: ios uicollectionview

我有UICollectionView使用流式布局,我试图获得与具有可读内容宽度的UITableViewController相同的边距。

我最接近匹配此布局行为的是在UICollectionViewController中嵌入UIViewController并具有嵌入式视图"遵循可读宽度"。

UICollectionViewController embedded in UIViewController

这里的蓝绿色是UIViewController,鲑鱼的颜色是UICollectionViewController。问题是青色区域没有滚动UICollectionView,滚动指示器也不像你期望的那样沿着屏幕的边缘。

我的问题是:

  

如何在不必嵌入UICollectionViewController的情况下实现此布局?

我的猜测是,我可以以某种方式设置UICollectionView左右部分插图以匹配可读内容指南边距,并通过覆盖viewWillTransition(to size: with coordinator:)并观察UIContentSizeCategoryDidChange通知来更新它们,但我和#39;我不知道该怎么做。

2 个答案:

答案 0 :(得分:0)

您的预感是正确的,最简单的方法是通过集合视图的insetForSection。以我的经验,这是必需的:

  • 返回集合视图的directionalLayoutMargins作为插图(使用.leading和。trailing
  • 通过collectionView.insetsLayoutMarginsFromSafeArea = false禁用自动安全区域处理
  • 使用directionalLayoutMargins手动设置集合视图的view.readableContentGuide.layoutFrame.origin.x。请注意,我使用的是 view .visibleContentGuide,而不是collectionView的。
  • 无论何时directionalLayoutMargins,以完全相同的方式更新viewLayoutMarginsDidChange

仍然很高兴知道如何在没有任何类型的容器的情况下完成此操作

答案 1 :(得分:0)

为了解决Swift 5.1和iOS 13的问题,您可以将流程布局的sectionInsetReference属性设置为.fromLayoutMargins,将集合视图的insetsLayoutMarginsFromSafeArea属性设置为{{1} },然后将集合视图的layoutMargins属性设置为与false的插图匹配。

以下两个示例代码显示了可能的实现方式,以使收集视图的内容宽度可读。


#1。使用readableContentGuide

UICollectionViewDelegateFlowLayout
import UIKit

class CollectionViewController: UICollectionViewController {

    let inset: CGFloat = 10
    let minimumLineSpacing: CGFloat = 10
    let minimumInteritemSpacing: CGFloat = 10
    let cellsPerRow = 5

    override func viewDidLoad() {
        super.viewDidLoad()

        title = "Demo"

        guard let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }
        layout.sectionInsetReference = .fromLayoutMargins
        collectionView.insetsLayoutMarginsFromSafeArea = false
        collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
    }

    override func viewWillLayoutSubviews() {
        let xOrigin = view.readableContentGuide.layoutFrame.origin.x
        collectionView.layoutMargins = UIEdgeInsets(top: 0, left: xOrigin, bottom: 0, right: xOrigin)
    }

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

    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
        cell.backgroundColor = UIColor.orange
        return cell
    }

}

#2。子类化extension CollectionViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: inset, left: inset, bottom: inset, right: inset) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return minimumLineSpacing } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return minimumInteritemSpacing } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let marginsAndInsets = inset * 2 + collectionView.layoutMargins.left + collectionView.layoutMargins.right + minimumInteritemSpacing * CGFloat(cellsPerRow - 1) let itemWidth = ((collectionView.bounds.size.width - marginsAndInsets) / CGFloat(cellsPerRow)).rounded(.down) return CGSize(width: itemWidth, height: itemWidth) } }

ColumnFlowLayout.swift

UICollectionViewFlowLayout

CollectionViewController.swift

import UIKit

class ColumnFlowLayout: UICollectionViewFlowLayout {

    let cellsPerRow: Int

    init(cellsPerRow: Int, minimumInteritemSpacing: CGFloat = 0, minimumLineSpacing: CGFloat = 0, sectionInset: UIEdgeInsets = .zero) {
        self.cellsPerRow = cellsPerRow
        super.init()

        self.sectionInsetReference = .fromLayoutMargins
        self.minimumInteritemSpacing = minimumInteritemSpacing
        self.minimumLineSpacing = minimumLineSpacing
        self.sectionInset = sectionInset
    }

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

    override func prepare() {
        super.prepare()

        guard let collectionView = collectionView else { return }
        let marginsAndInsets = sectionInset.left + sectionInset.right + collectionView.layoutMargins.left + collectionView.layoutMargins.right + minimumInteritemSpacing * CGFloat(cellsPerRow - 1)
        let itemWidth = ((collectionView.bounds.size.width - marginsAndInsets) / CGFloat(cellsPerRow)).rounded(.down)
        itemSize = CGSize(width: itemWidth, height: itemWidth)
    }

}

在iPhone Xs Max上显示:

enter image description here