UICollectionView 使用辅助功能自动调整具有动态列数的单元格

UICollectionView autosize cell with dynamic number of columns using Accessibility

我正在尝试模仿当前快捷方式应用程序 UICollectionView 的行为,其中项目的默认显示采用 2 列布局,但根据字体大小,它会更改为单列,单元格占据collection 视图的全宽。

我正在将动态类型添加到我的单元格标签,如果用户转到 phone 辅助功能并增加字体大小,我的标签也会增加,但现在标签字体增加但单元格只会增加在高度上,我的 collection 视图最终变成了两列,单元格非常高。

我目前使用的是没有任何自定义的基本流布局。我没有可用的或好的代码可以分享,但我正在寻找有关实现此目标的最佳方法的建议。

我的目标是 iOS 14,并使用 swift 5。

编辑 感谢 Witek 的回答,我能够使用 UICollectionViewCompositionalLayout 非常轻松地完成此操作,而且我什至不必订阅更改,只需在我的布局中查询 traitCollection 就足够了。这是我的最终结果:

private func createCompositionalLayout() -> UICollectionViewLayout {
    let layout = UICollectionViewCompositionalLayout { (sectionIndex: Int,
                                                        layoutEnvironment: NSCollectionLayoutEnvironment) -> NSCollectionLayoutSection? in
        
        let columns = self.traitCollection.preferredContentSizeCategory.isAccessibilityCategory ? 1 : 2
        
        // Define Item Size
        let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
        
        // Create Item
        let item = NSCollectionLayoutItem(layoutSize: itemSize)
        
        // Define Group Size
        let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .estimated(150.0))
        
        // Create Group
        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: columns)
        group.interItemSpacing = .fixed(10.0)
        
        // Create Section
        let section = NSCollectionLayoutSection(group: group)
        
        // Configure Section
        section.contentInsets = NSDirectionalEdgeInsets(top: 10.0, leading: 10.0, bottom: 10.0, trailing: 10.0)
        
        section.interGroupSpacing = 10
        return section
    }
    
    return layout
}

您可以观察 UIContentSizeCategory.didChangeNotification 并根据通知中传递的 newValueUserInfoKey 值更改列数(单元格大小)。

@objc private func sizeCategoryDidChange() {
    collectionView.reloadData()
}
NotificationCenter.default.addObserver(
    self, selector: #selector(sizeCategoryDidChange),
    name: UIContentSizeCategory.didChangeNotification, object: nil
)

首选内容大小类别也可以很容易地从 UIApplication.shared

中检索到
let contentSizeCategory = UIApplication.shared.preferredContentSizeCategory

快捷方式应用程序似乎根据 isAccessibilityCategory 属性 进行布局,以确定当前内容类别是否属于可访问性类别之一

let cellWidth: CGFloat
let padding: CGFloat = 16
if contentSizeCategory.isAccessibilityCategory {
    // single column, full width with padding
    cellWidth = collectionView.bounds.width - (padding * 2)
} else {
    // double column, half width with padding
    cellWidth = (collectionView.bounds.width - (padding * 3)) / 2 
}

文档: