우리는 이렇게 생긴 태그뷰를 만들고자 한다.
compositional layout을 이용하면 자동으로 width를 조절할 수 있고 여백에 따라 아래 행으로 줄바꿈되므로 쉽게 layout을 잡을 수 있다.
private let collectionView: UICollectionView = {
let layout = LeftAlignedCollectionViewFlowLayout()
layout.minimumLineSpacing = 12
layout.minimumInteritemSpacing = 8
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = Color.bbangWhite
collectionView.showsVerticalScrollIndicator = false
collectionView.register(cell: TagCell.self)
collectionView.contentInset = UIEdgeInsets(top: .zero, left: 16, bottom: 76, right: 16)
return collectionView
}()
collectionView.delegate = self
extension MakeBreadTagViewController: UICollectionViewDelegateFlowLayout {
func collectionView(
_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath
) -> CGSize {
let label = UILabel().then {
$0.font = NotoSansKR.regular.of(size: 16)
$0.text = tagList[indexPath.item]
$0.sizeToFit()
}
let size = label.frame.size
return CGSize(width: size.width + 60, height: size.height + 32)
}
}
cell 사이즈를 동적으로 계산해줄 수 없기 때문에 해당 폰트의 크기를 계산, 좌우 여백을 더하여 각각의 Cell을 지정해준다.
그러나 우리는 왼쪽으로 정렬된 Tag View를 만들고 싶으므로 UICollectionViewFlowLayout을 상속받아서 custom해준다.
private class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
let attributes = super.layoutAttributesForElements(in: rect)
var leftMargin = sectionInset.left
var maxY: CGFloat = -1.0
attributes?.forEach { layoutAttribute in
if layoutAttribute.representedElementCategory == .cell {
if layoutAttribute.frame.origin.y >= maxY {
leftMargin = sectionInset.left
}
layoutAttribute.frame.origin.x = leftMargin
leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
maxY = max(layoutAttribute.frame.maxY, maxY)
}
}
return attributes
}
}
끝! 구현은 했지만 뭔가 찝찝하다. 필요 없는 UILabel를 선언하여 크기를 구하고, 왼쪽 정렬하는 layout을 따로 정의하고.. 다른 방법이 있을 게 분명해!!
private lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: createTagLayout())
collectionView.backgroundColor = Color.bbangWhite
collectionView.showsVerticalScrollIndicator = false
collectionView.register(cell: TagCell.self)
collectionView.showsHorizontalScrollIndicator = false
collectionView.showsVerticalScrollIndicator = false
return collectionView
}()
private func createTagLayout() -> UICollectionViewLayout {
let itemSize = NSCollectionLayoutSize(
widthDimension: .estimated(60),
heightDimension: .absolute(55)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .absolute(55)
)
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: groupSize,
subitems: [item]
)
group.interItemSpacing = .fixed(8)
let section = NSCollectionLayoutSection(group: group)
section.interGroupSpacing = 12
section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 76, trailing: 16)
let config = UICollectionViewCompositionalLayoutConfiguration()
config.scrollDirection = .vertical
let layout = UICollectionViewCompositionalLayout(section: section)
layout.configuration = config
return layout
}
}
너무 간단하게 끝!
자동으로 사이즈 계산이 되기때문에 Cell만 AutoLayout을 잘 잡아준다면, 자동으로 잘 잡힐것이다.
Hi I am using a solution similar to your post. But I'm having issues. This is my stackoverflow link, can you check it out?