Modern Collection View [2] - List in Collection View | List Cell & Content Configuration
UICollectionViewLayoutListConfiguration
을 통한 리스트 타입 선택private var listAppearance: UICollectionLayoutListConfiguration.Appearance = .insetGrouped
private lazy var listLayout: UICollectionViewLayout = {
return UICollectionViewCompositionalLayout { _ , layoutEnvironment -> NSCollectionLayoutSection? in
var listConfig = UICollectionLayoutListConfiguration(appearance: self.listAppearance)
listConfig.headerMode = .supplementary
return NSCollectionLayoutSection.list(using: listConfig, layoutEnvironment: layoutEnvironment)
}
}()
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: listLayout)
private var cellRegistration: UICollectionView.CellRegistration<UICollectionViewListCell, Character>!
UICollectionViewListCell
이라는 디폴트로 제공하는 셀 사용cellRegistration = .init(handler: { [weak self] cell, _, model in
guard let self = self else { return }
var content = cell.defaultContentConfiguration()
content.text = model.name
content.secondaryText = model.job
content.image = UIImage(named: model.imageName)
content.imageProperties.maximumSize = .init(width: 60, height: 60)
content.imageProperties.cornerRadius = 30
cell.contentConfiguration = content
if self.selectedCharacters.contains(model) {
cell.accessories = [.checkmark(), .disclosureIndicator()]
} else {
cell.accessories = [.disclosureIndicator()]
}
})
contentConfiguration
이라는 프로퍼티를 통해 UI를 그림 private var headerRegistration: UICollectionView.SupplementaryRegistration<UICollectionViewListCell>!
headerRegistration = .init(elementKind: UICollectionView.elementKindSectionHeader, handler: { [weak self] cell, _, indexPath in
guard let self = self else { return }
let sectionedCharacter = self.sectionedCharacters[indexPath.section]
var content = cell.defaultContentConfiguration()
content.text = sectionedCharacter.headerTitleText
cell.contentConfiguration = content
})
defaultContentConfiguration()
을 이번에도 사용하기import UIKit
import SwiftUI
class CharacterListViewController: UIViewController {
private var collectionView: UICollectionView!
private lazy var segmentedControl: UISegmentedControl = {
let control = UISegmentedControl(items: ["Inset", "Plain", "Grouped", "Sidebar"])
control.selectedSegmentIndex = 0
control.addTarget(self, action: #selector(didTapControl), for: .valueChanged)
return control
}()
private var sectionedCharacters: [SectionCharacters] = Universe.ff7r.sectionedStubs {
didSet {
collectionView.reloadData()
}
}
private var selectedCharacters = Set<Character>()
private var cellRegistration: UICollectionView.CellRegistration<UICollectionViewListCell, Character>!
private var headerRegistration: UICollectionView.SupplementaryRegistration<UICollectionViewListCell>!
private var listAppearance: UICollectionLayoutListConfiguration.Appearance = .insetGrouped
private lazy var listLayout: UICollectionViewLayout = {
return UICollectionViewCompositionalLayout { _ , layoutEnvironment -> NSCollectionLayoutSection? in
var listConfig = UICollectionLayoutListConfiguration(appearance: self.listAppearance)
listConfig.headerMode = .supplementary
return NSCollectionLayoutSection.list(using: listConfig, layoutEnvironment: layoutEnvironment)
}
}()
override func viewDidLoad() {
super.viewDidLoad()
setUI()
}
private func setUI() {
view.backgroundColor = .systemBackground
navigationItem.titleView = segmentedControl
collectionView = UICollectionView(frame: view.bounds, collectionViewLayout: listLayout)
collectionView.backgroundColor = .systemBackground
collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(collectionView)
cellRegistration = .init(handler: { [weak self] cell, _, model in
guard let self = self else { return }
var content = cell.defaultContentConfiguration()
content.text = model.name
content.secondaryText = model.job
content.image = UIImage(named: model.imageName)
content.imageProperties.maximumSize = .init(width: 60, height: 60)
content.imageProperties.cornerRadius = 30
cell.contentConfiguration = content
if self.selectedCharacters.contains(model) {
cell.accessories = [.checkmark(), .disclosureIndicator()]
} else {
cell.accessories = [.disclosureIndicator()]
}
})
headerRegistration = .init(elementKind: UICollectionView.elementKindSectionHeader, handler: { [weak self] cell, _, indexPath in
guard let self = self else { return }
let sectionedCharacter = self.sectionedCharacters[indexPath.section]
var content = cell.defaultContentConfiguration()
content.text = sectionedCharacter.headerTitleText
cell.contentConfiguration = content
})
collectionView.dataSource = self
collectionView.delegate = self
}
@objc private func didTapControl() {
switch segmentedControl.selectedSegmentIndex {
case 0: listAppearance = .insetGrouped
case 1: listAppearance = .plain
case 2: listAppearance = .grouped
default: listAppearance = .sidebar
}
collectionView.collectionViewLayout.invalidateLayout()
}
}
appearance
결정
extension CharacterListViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let item = sectionedCharacters[indexPath.section].characters[indexPath.item]
if selectedCharacters.contains(item) {
selectedCharacters.remove(item)
} else {
selectedCharacters.insert(item)
}
collectionView.performBatchUpdates { [weak self] in
self?.collectionView.reloadItems(at: [indexPath])
}
}
}
extension CharacterListViewController: UICollectionViewDataSource {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return sectionedCharacters.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return sectionedCharacters[section].characters.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let model = sectionedCharacters[indexPath.section].characters[indexPath.item]
let cell = collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: model)
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
let header = collectionView.dequeueConfiguredReusableSupplementary(using: headerRegistration, for: indexPath)
return header
}
}