UICollectionView From Scratch [1] - CollectionViewCell & Supplementary View
private lazy var verticalStack: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [imageView, textLabel])
stackView.axis = .vertical
stackView.alignment = .center
stackView.spacing = 8
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
private func setUI() {
contentView.addSubview(verticalStack)
let verticalStackViewConstraints = [
verticalStack.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
verticalStack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8),
verticalStack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 8),
verticalStack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 8)
]
NSLayoutConstraint.activate(verticalStackViewConstraints)
let imageViewConstraints = [
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor)
]
NSLayoutConstraint.activate(imageViewConstraints)
}
self-sizing
뷰를 구현하기 위해 오토 레이아웃 적용contentView
기준으로 셀프 사이징하려는 뷰의 레이아웃을 조정struct CharacterCellViewRepresentable: UIViewRepresentable {
let character: Character
func makeUIView(context: Context) -> some UIView {
let cell = CharacterCell()
cell.configure(with: character)
return cell
}
func updateUIView(_ uiView: UIViewType, context: Context) {
}
}
UIViewRepresentable
클래스mkaeUIView
함수를 통해 표현하고자 하는 UIKit 컴포넌트를 리턴let character
와 같은 구조체 내 값을 통해 표현할 수 있음struct CharacterCell_Previews: PreviewProvider {
static var previews: some View {
Group {
ScrollView {
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible()), GridItem(.flexible())]) {
ForEach(Universe.ff7r.stubs) { character in
CharacterCellViewRepresentable(character: character)
.frame(width: 120, height: 150)
}
}
}
}
}
}
UIViewRepresentable
을 사용하는 까닭import UIKit
import SwiftUI
class CharacterCell: UICollectionViewCell {
private let imageView: RoundedImageView = {
let imageView = RoundedImageView()
imageView.contentMode = .scaleAspectFit
return imageView
}()
private let textLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .caption2)
label.adjustsFontForContentSizeCategory = true
label.textAlignment = .center
return label
}()
private lazy var verticalStack: UIStackView = {
let stackView = UIStackView(arrangedSubviews: [imageView, textLabel])
stackView.axis = .vertical
stackView.alignment = .center
stackView.spacing = 8
stackView.translatesAutoresizingMaskIntoConstraints = false
return stackView
}()
override init(frame: CGRect) {
super.init(frame: frame)
setUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func prepareForReuse() {
super.prepareForReuse()
textLabel.text = nil
imageView.image = nil
}
private func setUI() {
contentView.addSubview(verticalStack)
let verticalStackViewConstraints = [
verticalStack.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
verticalStack.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8),
verticalStack.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: 8),
verticalStack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: 8)
]
NSLayoutConstraint.activate(verticalStackViewConstraints)
let imageViewConstraints = [
imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor)
]
NSLayoutConstraint.activate(imageViewConstraints)
}
func configure(with model: Character) {
textLabel.text = model.name
imageView.image = UIImage(named: model.imageName)
}
}
import UIKit
import SwiftUI
class HeaderView: UICollectionReusableView {
private let textLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .headline)
label.adjustsFontForContentSizeCategory = true
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
setUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setUI() {
addSubview(textLabel)
let textLabelConstraints = [
textLabel.topAnchor.constraint(equalTo: topAnchor, constant: 16),
textLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16),
textLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -16),
textLabel.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -16)
]
NSLayoutConstraint.activate(textLabelConstraints)
}
func configure(with title: String) {
textLabel.text = title
}
}