#swift #uicollectionview #uikit #uicollectionviewlistcell #uicollectionviewlist
Вопрос:
В настоящее время у меня есть следующий макет:
Но я хочу получить этот макет для заголовков (развернутое состояние):
Поэтому, по существу, мне нужно пользовательское представление для индикатора раскрытия, потому что для развернутого состояния он должен указывать снизу, а для свернутого состояния он должен указывать сверху (см. Рисунок выше). Кроме того, индикатор раскрытия должен быть слева.
Что я сделал до сих пор
С помощью этого кода я получаю первый пример:
class ViewController: UIViewController {
enum ListItem: Hashable {
case header(HeaderItem)
case symbol(SFSymbolItem)
}
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewLayout())
var dataSource: UICollectionViewDiffableDataSource<HeaderItem, ListItem>!
override func viewDidLoad() {
super.viewDidLoad()
configureCollectionView()
setupDataSource()
updateDate(items: HeaderItem.modelObjects)
}
private func configureCollectionView() {
let layoutConfig = UICollectionLayoutListConfiguration(appearance: .plain)
let listLayout = UICollectionViewCompositionalLayout.list(using: layoutConfig)
collectionView.register(CustomListCell.self, forCellWithReuseIdentifier: CustomListCell.reuseID)
collectionView.collectionViewLayout = listLayout
view.addSubview(collectionView)
collectionView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(collectionView)
NSLayoutConstraint.activate([
collectionView.topAnchor.constraint(equalTo: view.topAnchor),
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
collectionView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
private func setupDataSource() {
let headerCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, HeaderItem> {
(cell, indexPath, headerItem) in
var config = cell.defaultContentConfiguration()
config.text = headerItem.title
cell.contentConfiguration = config
let headerDisclosureOption = UICellAccessory.OutlineDisclosureOptions(style: .header)
cell.accessories = [.outlineDisclosure(options: headerDisclosureOption)]
//cell.accessories = [.customView(configuration: .init(customView: UIView(), placement: .trailing(displayed: .always, at: .center), isHidden: <#T##Bool?#>, reservedLayoutWidth: <#T##UICellAccessory.LayoutDimension?#>, tintColor: <#T##UIColor?#>, maintainsFixedSize: <#T##Bool?#>))]
}
let symbolCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, SFSymbolItem> {
(cell, indexPath, symbolItem) in
var config = cell.defaultContentConfiguration()
config.text = symbolItem.name
cell.contentConfiguration = config
}
dataSource = UICollectionViewDiffableDataSource<HeaderItem, ListItem>(collectionView: collectionView) {
(collectionView, indexPath, listItem) -> UICollectionViewCell? in
switch listItem {
case .header(let headerItem):
// Dequeue header cell
let cell = collectionView.dequeueConfiguredReusableCell(using: headerCellRegistration,
for: indexPath,
item: headerItem)
return cell
case .symbol(let symbolItem):
// Dequeue symbol cell
let cell = collectionView.dequeueConfiguredReusableCell(using: symbolCellRegistration,
for: indexPath,
item: symbolItem)
return cell
}
}
}
private func updateDate(items: [HeaderItem]) {
var snapshot = NSDiffableDataSourceSnapshot<HeaderItem, ListItem>()
snapshot.appendSections(items)
for headerItem in items {
//section snapshot
var sectionSnapshot = NSDiffableDataSourceSectionSnapshot<ListItem>()
let headerListItem = ListItem.header(headerItem)
sectionSnapshot.append([headerListItem])
let symbolListItemArray = headerItem.symbols.map { ListItem.symbol($0) }
sectionSnapshot.append(symbolListItemArray, to: headerListItem)
dataSource.apply(sectionSnapshot, to: headerItem, animatingDifferences: false)
}
}
}
Model:
struct HeaderItem: Hashable {
let title: String
let symbols: [SFSymbolItem]
}
struct SFSymbolItem: Hashable {
let name: String
let image: UIImage
init(name: String) {
self.name = name
self.image = UIImage(systemName: name)!
}
}
extension HeaderItem {
static let modelObjects = [
HeaderItem(title: "Communication", symbols: [
SFSymbolItem(name: "mic"),
SFSymbolItem(name: "mic.fill"),
SFSymbolItem(name: "message"),
SFSymbolItem(name: "message.fill"),
]),
HeaderItem(title: "Weather", symbols: [
SFSymbolItem(name: "sun.min"),
SFSymbolItem(name: "sun.min.fill"),
SFSymbolItem(name: "sunset"),
SFSymbolItem(name: "sunset.fill"),
]),
HeaderItem(title: "Objects amp; Tools", symbols: [
SFSymbolItem(name: "pencil"),
SFSymbolItem(name: "pencil.circle"),
SFSymbolItem(name: "highlighter"),
SFSymbolItem(name: "pencil.and.outline"),
]),
]
}
Edit:
I was able to get closer to the desired result by using .customView(...)
as accesory type.
let testAction = UIAction(image: UIImage(systemName: "chevron.up"), handler: { [weak self] _ in
//expand / collapse programmatically
})
let testBtn = UIButton(primaryAction: testAction)
let customAccessory = UICellAccessory.CustomViewConfiguration(
customView: testBtn,
placement: .leading(displayed: .always))
cell.accessories = [.customView(configuration: customAccessory)]
Можно ли свернуть / развернуть программно, щелкнув на пользовательском представлении?