Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- Human interface guide
- 리펙토링
- uitableview
- Protocol
- HIG
- RxCocoa
- swift documentation
- Observable
- tableView
- clean architecture
- ribs
- 리팩토링
- Xcode
- rxswift
- 스위프트
- collectionview
- map
- 리펙터링
- Clean Code
- UICollectionView
- Refactoring
- uiscrollview
- swiftUI
- UITextView
- MVVM
- SWIFT
- 애니메이션
- combine
- ios
- 클린 코드
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 4. UICollectionViewCompositionalLayout - 개념 (orthogonalScrollingBehavior, 수평 스크롤, visibleItemsInvalidationHandler) 본문
iOS 응용 (swift)
[iOS - swift] 4. UICollectionViewCompositionalLayout - 개념 (orthogonalScrollingBehavior, 수평 스크롤, visibleItemsInvalidationHandler)
jake-kim 2022. 4. 22. 23:591. UICollectionViewCompositionalLayout - 개념 (section, group, item)
2. UICollectionViewCompositionalLayout - 개념 SupplementaryView, Header, Footer)
3. UICollectionViewCompositionalLayout - 개념 (DecorationView, Badge, NSCollectionLayoutAnchor)
4. UICollectionViewCompositionalLayout - 개념 (orthogonalScrollingBehavior, 수평 스크롤, visibleItemsInvalidationHandler)
5. UICollectionViewCompositionalLayout - 응용 (유튜브 뮤직 앱 UI 구현)
orthogonalScrollingBehavior (수평 스크롤)
- 특정 Section에 대해 스크롤 방향을 반대로 설정할 수 있는 방법
- 기존에는 수평스크롤을 넣고 싶은 경우, cell안에 collectionView를 하나 더 넣어서 수평 스크롤을 구현했지만 orthogonalScrollingBehavior를 사용하면 간결
- 크게 자연스럽게 스크롤 되는 continuous와 paging 스크롤 되는 paging이 존재
- 5가지 속성이 존재
// Standard scroll view behavior: UIScrollViewDecelerationRateNormal
case continuous
// Scrolling will come to rest on the leading edge of a group boundary
case continuousGroupLeadingBoundary
// Standard scroll view paging behavior (UIScrollViewDecelerationRateFast) with page size == extent of the collection view's bounds
case paging
// Fractional size paging behavior determined by the sections layout group's dimension
case groupPaging
// Same of group paging with additional leading and trailing content insets to center each group's contents along the orthogonal axis
case groupPagingCentered
.continous | paging |
- orthogonalScrollingBehavior는 section의 프로퍼티이므로 아래처럼 사용
- section.orthogonalScrollingBehavior = .continuous
private func getGridSection() -> NSCollectionLayoutSection {
let itemSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(0.3),
heightDimension: .fractionalHeight(1.0)
)
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 8, leading: 8, bottom: 8, trailing: 8)
let groupSize = NSCollectionLayoutSize(
widthDimension: .fractionalWidth(1.0),
heightDimension: .fractionalHeight(0.3)
)
// collectionView의 width에 3개의 아이템이 위치하도록 하는 것
let group = NSCollectionLayoutGroup.horizontal(
layoutSize: groupSize,
subitem: item,
count: 3
)
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .continuous
return section
}
- 사용하는쪽
private lazy var collectionView: UICollectionView = {
let view = UICollectionView(frame: .zero, collectionViewLayout: self.getLayout())
view.isScrollEnabled = true
view.showsHorizontalScrollIndicator = false
view.showsVerticalScrollIndicator = true
view.contentInset = .zero
view.backgroundColor = .clear
view.clipsToBounds = true
view.register(MyCell.self, forCellWithReuseIdentifier: MyCell.id)
view.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(view)
return view
}()
private func getLayout() -> UICollectionViewLayout {
return UICollectionViewCompositionalLayout { sectionIndex, env -> NSCollectionLayoutSection? in
switch self.dataSource[sectionIndex] {
case .main:
return self.getListSection()
case .sub:
return self.getGridSection()
}
}
}
visibleItemsInvalidationHandler
- 현재 보여지고 있는 화면에 어떤 항목이 표시되는지 알 수 있는 api
- section의 visibleItemsInvalidationHandler 프로퍼티에 클로저 내부에서 처리
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .paging
section.visibleItemsInvalidationHandler = { [weak self] (visibleItems, offset, env) in
guard let ss = self else { return }
let normalizedOffsetX = offset.x
let centerPoint = CGPoint(x: normalizedOffsetX + ss.collectionView.bounds.width / 2, y: 20)
visibleItems.forEach({ item in
guard let cell = ss.collectionView.cellForItem(at: item.indexPath) else { return }
UIView.animate(withDuration: 0.3) {
cell.transform = item.frame.contains(centerPoint) ? .identity : CGAffineTransform(scaleX: 0.9, y: 0.9)
}
})
}
...
// 최초에 위 애니메이션이 적용되어야 하므로, 런타임에서 뷰의 크기가 정해졌을 때 performBatchUpdates 호출
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.collectionView.performBatchUpdates(nil, completion: nil)
}
* 전체 코드: https://github.com/JK0369/ExCompositionalLayout
* 참고
https://betterprogramming.pub/super-easy-compositional-uicollectionviews-in-swift-f0fa6a2c108d
'iOS 응용 (swift)' 카테고리의 다른 글
Comments