UICollectionViewCompositionalLayout - 在部分或组中居中项目
UICollectionViewCompositionalLayout - center items in sections or groups
我用新的合成材料设置了一个集合视图及其布局,它非常酷,它似乎非常可扩展,但我找不到使项目在集合中居中的方法,这是IMO 一个人们想象得到支持的基本功能..
我有的是:
完成此代码:
UICollectionViewCompositionalLayout { section, env in
let tagDefaultSize = CGSize(width: 100, height: 40)
let item = NSCollectionLayoutItem(
layoutSize: NSCollectionLayoutSize(widthDimension: .estimated(tagDefaultSize.width), heightDimension: .absolute(tagDefaultSize.height))
)
item.edgeSpacing = NSCollectionLayoutEdgeSpacing(
leading: .fixed(0),
top: .fixed(0),
trailing: .fixed(8),
bottom: .fixed(0)
)
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(tagDefaultSize.height)),
subitems: [item]
)
group.edgeSpacing = NSCollectionLayoutEdgeSpacing(
leading: .flexible(8),
top: .fixed(0),
trailing: .fixed(8),
bottom: .fixed(8)
)
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(
top: 30,
leading: 20,
bottom: 40,
trailing: 20
)
return section
}
但我需要的是:
有没有人对此有好运?谢谢
我找到了一个解决方案,使用
custom(layoutSize: NSCollectionLayoutSize, itemProvider: @escaping NSCollectionLayoutGroupCustomItemProvider)
我创建了以下扩展,它计算组中每个元素的帧,将尽可能多的项目居中放置在每一行上
extension NSCollectionLayoutGroup {
static func verticallyCentered(cellSizes: [CGSize], interItemSpacing: CGFloat = 10, interRowSpacing: CGFloat = 10) -> NSCollectionLayoutGroup {
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(100))
return custom(layoutSize: groupSize) { environment in
var items: [NSCollectionLayoutGroupCustomItem] = []
var yPos: CGFloat = environment.container.contentInsets.top
var rowSizes: [CGSize] = []
func totalWidth() -> CGFloat {
rowSizes.map(\.width).reduce(0) {
[=11=] == 0 ? : [=11=] + interItemSpacing +
}
}
func addRowItems() {
var xPos = (environment.container.effectiveContentSize.width - totalWidth())/2 + environment.container.contentInsets.leading
let maxItemHeight = rowSizes.map(\.height).max() ?? 0
let rowItems: [NSCollectionLayoutGroupCustomItem] = rowSizes.map {
let rect = CGRect(origin: CGPoint(x: xPos, y: yPos + (maxItemHeight - [=11=].height) / 2), size: [=11=])
xPos += ([=11=].width + interItemSpacing)
return NSCollectionLayoutGroupCustomItem(frame: rect)
}
items.append(contentsOf: rowItems)
}
for (index, cellSize) in cellSizes.enumerated() {
rowSizes.append(cellSize)
if totalWidth() > environment.container.effectiveContentSize.width {
rowSizes.removeLast()
addRowItems()
yPos += (cellSize.height + interRowSpacing)
rowSizes = [cellSize]
}
if index == cellSizes.count - 1 {
addRowItems()
}
}
return items
}
}
}
然后创建一个布局部分,其中包含一个包含该部分中所有项目的组。首先,您首先需要计算该部分中所有元素的大小,然后将它们传递给上面的函数,就像这样(注意我在这里使用的是 DiffableDataSource)…
func someLayoutSection(sectionIndex: Int) -> NSCollectionLayoutSection {
let itemCount = collectionView.numberOfItems(inSection: sectionIndex)
let cell = SomeCell(frame: .zero)
let cellSizes: [CGSize] = (0..<itemCount).compactMap {
switch diffableDataSource.itemIdentifier(for: IndexPath(item: [=12=], section: sectionIndex)) {
case let .someItem(something):
cell.configure(thing: something)
return cell.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
default:
return nil
}
}
let group = NSCollectionLayoutGroup.verticallyCentered(cellSizes: cellSizes)
group.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20).scaled
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 0, bottom: 20, trailing: 0)
return section
}
然后创建布局...
func makeLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in
let section = diffableDataSource.snapshot().sectionIdentifiers[sectionIndex]
switch section {
case .someSection:
return someLayoutSection(sectionIndex: sectionIndex)
case .otherSection:
// etc
}
}
我用新的合成材料设置了一个集合视图及其布局,它非常酷,它似乎非常可扩展,但我找不到使项目在集合中居中的方法,这是IMO 一个人们想象得到支持的基本功能..
我有的是:
完成此代码:
UICollectionViewCompositionalLayout { section, env in
let tagDefaultSize = CGSize(width: 100, height: 40)
let item = NSCollectionLayoutItem(
layoutSize: NSCollectionLayoutSize(widthDimension: .estimated(tagDefaultSize.width), heightDimension: .absolute(tagDefaultSize.height))
)
item.edgeSpacing = NSCollectionLayoutEdgeSpacing(
leading: .fixed(0),
top: .fixed(0),
trailing: .fixed(8),
bottom: .fixed(0)
)
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(tagDefaultSize.height)),
subitems: [item]
)
group.edgeSpacing = NSCollectionLayoutEdgeSpacing(
leading: .flexible(8),
top: .fixed(0),
trailing: .fixed(8),
bottom: .fixed(8)
)
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(
top: 30,
leading: 20,
bottom: 40,
trailing: 20
)
return section
}
但我需要的是:
有没有人对此有好运?谢谢
我找到了一个解决方案,使用
custom(layoutSize: NSCollectionLayoutSize, itemProvider: @escaping NSCollectionLayoutGroupCustomItemProvider)
我创建了以下扩展,它计算组中每个元素的帧,将尽可能多的项目居中放置在每一行上
extension NSCollectionLayoutGroup {
static func verticallyCentered(cellSizes: [CGSize], interItemSpacing: CGFloat = 10, interRowSpacing: CGFloat = 10) -> NSCollectionLayoutGroup {
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(100))
return custom(layoutSize: groupSize) { environment in
var items: [NSCollectionLayoutGroupCustomItem] = []
var yPos: CGFloat = environment.container.contentInsets.top
var rowSizes: [CGSize] = []
func totalWidth() -> CGFloat {
rowSizes.map(\.width).reduce(0) {
[=11=] == 0 ? : [=11=] + interItemSpacing +
}
}
func addRowItems() {
var xPos = (environment.container.effectiveContentSize.width - totalWidth())/2 + environment.container.contentInsets.leading
let maxItemHeight = rowSizes.map(\.height).max() ?? 0
let rowItems: [NSCollectionLayoutGroupCustomItem] = rowSizes.map {
let rect = CGRect(origin: CGPoint(x: xPos, y: yPos + (maxItemHeight - [=11=].height) / 2), size: [=11=])
xPos += ([=11=].width + interItemSpacing)
return NSCollectionLayoutGroupCustomItem(frame: rect)
}
items.append(contentsOf: rowItems)
}
for (index, cellSize) in cellSizes.enumerated() {
rowSizes.append(cellSize)
if totalWidth() > environment.container.effectiveContentSize.width {
rowSizes.removeLast()
addRowItems()
yPos += (cellSize.height + interRowSpacing)
rowSizes = [cellSize]
}
if index == cellSizes.count - 1 {
addRowItems()
}
}
return items
}
}
}
然后创建一个布局部分,其中包含一个包含该部分中所有项目的组。首先,您首先需要计算该部分中所有元素的大小,然后将它们传递给上面的函数,就像这样(注意我在这里使用的是 DiffableDataSource)…
func someLayoutSection(sectionIndex: Int) -> NSCollectionLayoutSection {
let itemCount = collectionView.numberOfItems(inSection: sectionIndex)
let cell = SomeCell(frame: .zero)
let cellSizes: [CGSize] = (0..<itemCount).compactMap {
switch diffableDataSource.itemIdentifier(for: IndexPath(item: [=12=], section: sectionIndex)) {
case let .someItem(something):
cell.configure(thing: something)
return cell.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
default:
return nil
}
}
let group = NSCollectionLayoutGroup.verticallyCentered(cellSizes: cellSizes)
group.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 20, bottom: 0, trailing: 20).scaled
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: 20, leading: 0, bottom: 20, trailing: 0)
return section
}
然后创建布局...
func makeLayout() -> UICollectionViewLayout {
UICollectionViewCompositionalLayout { [unowned self] sectionIndex, environment in
let section = diffableDataSource.snapshot().sectionIdentifiers[sectionIndex]
switch section {
case .someSection:
return someLayoutSection(sectionIndex: sectionIndex)
case .otherSection:
// etc
}
}