提问人:Shivaditya kr 提问时间:10/13/2023 更新时间:10/19/2023 访问量:66
在 Compositional Layout 中自定义 UICollectionView 部分的拐角半径和颜色?
Customizing corner radius & colors for UICollectionView sections in Compositional Layout?
问:
我正在处理一个项目,其中我正在使用带有组合布局的 UICollectionView。我正在尝试将拐角半径添加到我的 UICollectionView 的节标题中。我正在使用 UICollectionViewCompositionalLayout 创建部分,并且我希望每个部分标题具有不同的角半径、颜色和设计。
下面是我的代码示例:
// Creating the compositional layout
let layout = UICollectionViewCompositionalLayout { sectionIndex, layoutEnvironment in
// configuring sections and items
}
// Registering section header
let headerRegistration = UICollectionView.SupplementaryRegistration
<HeaderCollectionViewCell>(elementKind: UICollectionView.elementKindSectionHeader) {
supplementaryView, string, indexPath in
// configuring header view
}
collectionView.collectionViewLayout = layout
collectionView.register(HeaderCollectionViewCell.self,
forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
withReuseIdentifier: "HeaderCollectionViewCell")
如何使用 UICollectionViewCompositionalLayout 为 UICollectionView 的每个部分标题添加不同的角半径、颜色和设计?有关此问题的任何帮助或指导将不胜感激。谢谢!
我试图通过在部分内创建装饰器来装饰它,但似乎我只能更改颜色而不能更改角半径。此外,我添加的颜色不符合部分约束。例如,如果我向某个部分添加水平填充,则该部分颜色会溢出该填充并扩展到屏幕宽度
答:
0赞
DonMag
10/16/2023
#1
您可以在注册块中执行此操作。
例如:
let headerRegistration = UICollectionView.SupplementaryRegistration
<TitleSupplementaryView>(elementKind: CompColumnsVC.sectionHeaderElementKind) {
(supplementaryView, string, indexPath) in
supplementaryView.label.text = "\(string) for section \(indexPath.section)"
// default background color / corner radius /
// text color / border color / border width
supplementaryView.backgroundColor = .lightGray
supplementaryView.layer.cornerRadius = 0.0
supplementaryView.layer.borderColor = UIColor.black.cgColor
supplementaryView.layer.borderWidth = 1.0
supplementaryView.label.textColor = .black
// specific background color / corner radius /
// text color / border color / border width
// for sections 0, 1, 2 (all the rest use default
switch indexPath.section {
case 0:
supplementaryView.backgroundColor = .cyan
supplementaryView.layer.cornerRadius = 6.0
case 1:
supplementaryView.backgroundColor = .systemBlue
supplementaryView.label.textColor = .white
supplementaryView.layer.cornerRadius = 12.0
case 2:
supplementaryView.backgroundColor = .yellow
supplementaryView.layer.cornerRadius = 16.0
supplementaryView.layer.borderWidth = 0.0
supplementaryView.layer.borderColor = UIColor.red.cgColor
default:
()
}
}
给我这个结果:
下面是一个完整的示例,基于
- 构图布局 ->
- 高级布局 ->
- 补充意见 ->
- 节眉/页脚
来自 Apple 的实现新式集合视图示例应用:From Apple's Implementing Modern Collection Views sample app:
简单的单标签集合视图单元格:
class SimpleCell: UICollectionViewCell {
let theLabel: UILabel = {
let v = UILabel()
return v
}()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() -> Void {
theLabel.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(theLabel)
let g = contentView.layoutMarginsGuide
NSLayoutConstraint.activate([
theLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 4.0),
theLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
theLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
theLabel.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -4.0),
])
contentView.layer.borderColor = UIColor(white: 0.9, alpha: 1.0).cgColor
contentView.layer.borderWidth = 1.0
}
}
节标题的可重用视图:
class TitleSupplementaryView: UICollectionReusableView {
let label = UILabel()
let bkgView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
label.translatesAutoresizingMaskIntoConstraints = false
bkgView.translatesAutoresizingMaskIntoConstraints = false
bkgView.addSubview(label)
addSubview(bkgView)
NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: bkgView.topAnchor, constant: 8.0),
label.leadingAnchor.constraint(equalTo: bkgView.leadingAnchor, constant: 8.0),
label.trailingAnchor.constraint(equalTo: bkgView.trailingAnchor, constant: -8.0),
label.bottomAnchor.constraint(equalTo: bkgView.bottomAnchor, constant: -8.0),
bkgView.topAnchor.constraint(equalTo: topAnchor, constant: 4.0),
bkgView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0.0),
bkgView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0.0),
bkgView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4.0),
])
label.font = .systemFont(ofSize: 14.0, weight: .light)
bkgView.backgroundColor = .clear
}
}
视图控制器类示例:
class CustomizeHeadersVC: UIViewController, UICollectionViewDelegate {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Int, Int>! = nil
override func viewDidLoad() {
super.viewDidLoad()
collectionView = UICollectionView(frame: .zero, collectionViewLayout: createLayout())
collectionView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(collectionView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
collectionView.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
collectionView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
collectionView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
collectionView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
])
configureDataSource()
collectionView.delegate = self
}
static let sectionHeaderElementKind = "section-header-element-kind"
func createLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(44))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 3
section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 6, trailing: 0)
let headerFooterSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(44))
let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
layoutSize: headerFooterSize,
elementKind: CustomizeHeadersVC.sectionHeaderElementKind, alignment: .top)
section.boundarySupplementaryItems = [sectionHeader]
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<SimpleCell, Int> { (cell, indexPath, identifier) in
// Populate the cell with our item description.
cell.theLabel.text = "\(indexPath)" // "\(indexPath.section),\(indexPath.item)"
}
let headerRegistration = UICollectionView.SupplementaryRegistration
<TitleSupplementaryView>(elementKind: CustomizeHeadersVC.sectionHeaderElementKind) {
(supplementaryView, string, indexPath) in
supplementaryView.label.text = "Section Header for section \(indexPath.section)"
// default background color / corner radius /
// text color / border color / border width
supplementaryView.bkgView.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
supplementaryView.bkgView.layer.cornerRadius = 0.0
supplementaryView.bkgView.layer.borderColor = UIColor.black.cgColor
supplementaryView.bkgView.layer.borderWidth = 1.0
supplementaryView.label.textColor = .black
// specific background color / corner radius /
// text color / border color / border width
// for sections ... cycle through 4 "styles"
switch indexPath.section % 4 {
case 0:
supplementaryView.bkgView.backgroundColor = .cyan
supplementaryView.bkgView.layer.cornerRadius = 6.0
case 1:
supplementaryView.bkgView.backgroundColor = .systemBlue
supplementaryView.label.textColor = .white
supplementaryView.bkgView.layer.cornerRadius = 12.0
supplementaryView.bkgView.layer.borderWidth = 2.0
case 2:
supplementaryView.bkgView.backgroundColor = .yellow
supplementaryView.bkgView.layer.cornerRadius = 16.0
supplementaryView.bkgView.layer.borderWidth = 0.0
supplementaryView.bkgView.layer.borderColor = UIColor.red.cgColor
default:
()
}
}
dataSource = UICollectionViewDiffableDataSource<Int, Int>(collectionView: collectionView) {
(collectionView: UICollectionView, indexPath: IndexPath, identifier: Int) -> UICollectionViewCell? in
return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: identifier)
}
dataSource.supplementaryViewProvider = { (view, kind, index) in
return self.collectionView.dequeueConfiguredReusableSupplementary(
using: headerRegistration, for: index)
}
// initial data
let itemsPerSection = 3
let sections = Array(0..<25)
var snapshot = NSDiffableDataSourceSnapshot<Int, Int>()
var itemOffset = 0
sections.forEach {
snapshot.appendSections([$0])
snapshot.appendItems(Array(itemOffset..<itemOffset + itemsPerSection))
itemOffset += itemsPerSection
}
dataSource.apply(snapshot, animatingDifferences: false)
}
}
输出 - 我们循环浏览 4 种不同的部分标题“样式”(背景和文本颜色、边框、角半径等):
编辑 - 评论后...
对上述代码稍作修改,以显示“部分背景”装饰视图......
剖面背景视图:
class SectionBackgroundView: UICollectionReusableView {
static let reuseIdentifier: String = "SectionBackgroundView"
let bkgView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
commonInit()
}
func commonInit() {
backgroundColor = .clear
bkgView.translatesAutoresizingMaskIntoConstraints = false
addSubview(bkgView)
NSLayoutConstraint.activate([
bkgView.topAnchor.constraint(equalTo: topAnchor, constant: 0.0),
bkgView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0.0),
bkgView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0.0),
bkgView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0.0),
])
}
}
视图控制器类示例:
class CustomizeHeadersVC: UIViewController, UICollectionViewDelegate {
var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Int, Int>! = nil
override func viewDidLoad() {
super.viewDidLoad()
collectionView = UICollectionView(frame: .zero, collectionViewLayout: createLayout())
collectionView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(collectionView)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
collectionView.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
collectionView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 8.0),
collectionView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -8.0),
collectionView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
])
configureDataSource()
collectionView.delegate = self
}
func collectionView(_ collectionView: UICollectionView, willDisplaySupplementaryView view: UICollectionReusableView, forElementKind elementKind: String, at indexPath: IndexPath) {
if elementKind == CustomizeHeadersVC.backgroundElementKind,
let v = view as? SectionBackgroundView
{
// default background color / corner radius /
// text color / border color / border width
v.bkgView.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
v.bkgView.layer.cornerRadius = 0.0
v.bkgView.layer.borderColor = UIColor.black.cgColor
v.bkgView.layer.borderWidth = 1.0
// specific background color / corner radius /
// text color / border color / border width
// for sections ... cycle through 4 "styles"
switch indexPath.section % 4 {
case 0:
v.bkgView.backgroundColor = .cyan
v.bkgView.layer.cornerRadius = 6.0
case 1:
v.bkgView.backgroundColor = .systemBlue
v.bkgView.layer.cornerRadius = 12.0
v.bkgView.layer.borderWidth = 2.0
case 2:
v.bkgView.backgroundColor = .systemYellow
v.bkgView.layer.cornerRadius = 16.0
v.bkgView.layer.borderWidth = 0.0
v.bkgView.layer.borderColor = UIColor.red.cgColor
default:
()
}
if let bc = v.bkgView.backgroundColor {
v.bkgView.backgroundColor = bc.withAlphaComponent(0.25)
}
}
}
static let sectionHeaderElementKind = "section-header-element-kind"
static let backgroundElementKind = "background-element-kind"
func createLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(44))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 3
section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 0, bottom: 6, trailing: 0)
section.contentInsets = NSDirectionalEdgeInsets(top: 8, leading: 20, bottom: 16, trailing: 20)
let headerFooterSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0),
heightDimension: .estimated(44))
let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
layoutSize: headerFooterSize,
elementKind: CustomizeHeadersVC.sectionHeaderElementKind, alignment: .top)
section.boundarySupplementaryItems = [sectionHeader]
section.decorationItems = [
NSCollectionLayoutDecorationItem.background(elementKind: CustomizeHeadersVC.backgroundElementKind)
]
let config = UICollectionViewCompositionalLayoutConfiguration()
config.interSectionSpacing = 12 // section spacing
let layout = UICollectionViewCompositionalLayout(section: section, configuration: config)
layout.register(SectionBackgroundView.self, forDecorationViewOfKind: CustomizeHeadersVC.backgroundElementKind)
return layout
}
func configureDataSource() {
let cellRegistration = UICollectionView.CellRegistration<SimpleCell, Int> { (cell, indexPath, identifier) in
// Populate the cell with our item description.
cell.theLabel.text = "\(indexPath)" // "\(indexPath.section),\(indexPath.item)"
}
let bkgRegistration = UICollectionView.SupplementaryRegistration
<SectionBackgroundView>(elementKind: CustomizeHeadersVC.backgroundElementKind) {
(supplementaryView, string, indexPath) in
supplementaryView.bkgView.backgroundColor = .green
}
let headerRegistration = UICollectionView.SupplementaryRegistration
<TitleSupplementaryView>(elementKind: CustomizeHeadersVC.sectionHeaderElementKind) {
(supplementaryView, string, indexPath) in
supplementaryView.label.text = "Section Header for section \(indexPath.section)"
// default background color / corner radius /
// text color / border color / border width
supplementaryView.bkgView.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
supplementaryView.bkgView.layer.cornerRadius = 0.0
supplementaryView.bkgView.layer.borderColor = UIColor.black.cgColor
supplementaryView.bkgView.layer.borderWidth = 1.0
supplementaryView.label.textColor = .black
// specific background color / corner radius /
// text color / border color / border width
// for sections ... cycle through 4 "styles"
switch indexPath.section % 4 {
case 0:
supplementaryView.bkgView.backgroundColor = .cyan
supplementaryView.bkgView.layer.cornerRadius = 6.0
case 1:
supplementaryView.bkgView.backgroundColor = .systemBlue
supplementaryView.label.textColor = .white
supplementaryView.bkgView.layer.cornerRadius = 12.0
supplementaryView.bkgView.layer.borderWidth = 2.0
case 2:
supplementaryView.bkgView.backgroundColor = .systemYellow
supplementaryView.bkgView.layer.cornerRadius = 16.0
supplementaryView.bkgView.layer.borderWidth = 0.0
supplementaryView.bkgView.layer.borderColor = UIColor.red.cgColor
default:
()
}
}
dataSource = UICollectionViewDiffableDataSource<Int, Int>(collectionView: collectionView) {
(collectionView: UICollectionView, indexPath: IndexPath, identifier: Int) -> UICollectionViewCell? in
return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: identifier)
}
dataSource.supplementaryViewProvider = { (view, kind, index) in
return self.collectionView.dequeueConfiguredReusableSupplementary(
using: headerRegistration, for: index)
}
// initial data
let itemsPerSection = 3
let sections = Array(0..<25)
var snapshot = NSDiffableDataSourceSnapshot<Int, Int>()
var itemOffset = 0
sections.forEach {
snapshot.appendSections([$0])
snapshot.appendItems(Array(itemOffset..<itemOffset + itemsPerSection))
itemOffset += itemsPerSection
}
dataSource.apply(snapshot, animatingDifferences: false)
}
}
结果:
评论
0赞
Shivaditya kr
10/16/2023
谢谢你的分享,我也想知道如何装饰我的小组,这样我就可以让每个部分元素都有不同的背景风格。
0赞
DonMag
10/16/2023
好吧,这是一个完全不同的问题。
0赞
DonMag
10/17/2023
@Shivadityakr - 快速搜索会得到很多结果。swift "UICollectionViewCompositionalLayout" section border
0赞
DonMag
10/18/2023
@Shivadityakr - 这是否更接近您想要的?i.stack.imgur.com/6StP7.png
0赞
Shivaditya kr
10/19/2023
嘿,我想,谢谢伙计
评论