[번외편][이론] iOS 사용성 최대로 올려보자! UICollectionView Custom Layout
이 포스팅은 "[번외편] 사용성 최대로 올려보자!"의 Series 중 일부입니다.
[번외편][이론] iOS 사용성 최대로 올려보자! UICollectionView Custom Layout
[번외편][실전] iOS 사용성 최대로 올려보자! UICollectionView Custom Layout
[번외편] iOS 사용성 최대로 올려보자! Shimmer
Creating Custom Layouts
UICollectionViewFlowLayout 클래스는 최적화 되어 있기 때문에
Custom Layout 구현해야 하는 이유를 고려해야 합니다.
- Grid, Linear 줄 바꿈 레이아웃의 한 방향 이상의 스크롤링이 필요할때
- 모든 셀 위치를 자주 변경하기 위하여 Custom Layout을 작성하는 것이 기존 FlowLayout을 수정하는 것보다 더 효과적 일 경우
Layout 객체는 데이터 소스에서 제공 한 정보를 사용하여 CollectionView의 Layout을 만듭니다.
Layout 과정에서 CollectionView가 알고있는 것과 모르는 것을 명심해야 합니다.
Layout 프로세스가 진행 중이므로 CollectionView에서 View의 Layout 또는 위치를 추적 할 수 없습니다.
따라서 Layout 객체가 CollectionView의 메소드를 호출하는 것을 제한하지는 않지만
Layout을 계산하는 데 필요한 데이터 이외의 다른 것에 대해서는 CollectionView에 의존하지 안됩니다.
Understanding the Core Layout Process
CollectionView는 Custom Layout 객체와 직접 작동하여 전체 Layout 프로세스를 관리합니다.
CollectionView에 Layout 정보가 필요하다고 판단되면 Layout 객체에 Layout 정보를 제공하도록 요청합니다.
예를 들어, CollectionView는 Layout 정보가 처음 표시되거나 크기가 조정될 때 Layout 정보를 요청합니다.
Layout 객체의 invalidateLayout 메서드를 호출하여 CollectionView에 Layout을 명시 적으로 업데이트하도록 지시 할 수도 있습니다.
이 메소드는 기존 Layout 정보를 버리고 Layout 객체가 새 Layout 정보를 생성하도록합니다.
Note: 조심하지 않으면 layout 객체의 invalidateLayout 메소드와 collection view의 reloadData 메소드와 혼동할수 있습니다.
invalidateLayout 메소드는 CollectionView의 존재하는 cell들과 하위 뷰들을 버리는 것이 아닙니다.
오히려 레이아웃 객체에게 아이템이 지워지거나, 추가 되거나, 이동할때 필연적으로 자체 모든 레이아웃 속성을 재연산 하도록 합니다.
데이터 소스 내의 데이터가 변경 된다면, reloadData 메소드가 적절 합니다
Layout 프로세스 중에 다음 순서로 호출됩니다.
1. preparedLayout 메소드를 사용하여 Layout 정보를 제공하는 데 필요한 선행 계산을 수행하십시오.
2. CollectionViewContentSize 메소드를 사용하여 초기 계산을 기반으로 전체 컨텐츠 영역의 전체 크기를 리턴하십시오.
3. LayoutAttributesForElementsInRect : 메소드를 사용하여 지정된 사각형에있는 Cell 및 View의 속성을 리턴하십시오.
prepareLayout은 Cell 및 View의 위치를 결정하는 데 필요한 계산을 수행 할 수있는 기회입니다.
최소한이 방법으로 충분한 정보를 계산하여 컨텐츠 영역의 전체 크기를 계산하고 2 단계의 CollectionView로 리턴하십시오.
CollectionView는 contentSize를 사용하여 해당 스크롤보기를 적절하게 구성합니다. 예를 들어, 계산 된 컨텐츠 크기가 현재 장치 화면의 경계를 넘어 수직 및 수평으로 확장되는 경우 스크롤보기는 양방향으로 동시에 스크롤 할 수 있도록 조정됩니다.
현재 스크롤 위치를 기준으로 layoutAttributesForElementsInRect : 메서드를 호출하여 표시되는 사각형과 같거나 같지 않을 수있는 특정 사각형의 셀 및보기의 특성을 요청합니다.
intersects(rect) 메소드를 사용하여 현재 보여지는 rect 포함되는 Attributes 리턴합니다.
Layout 이 완료된 후 Cell 또는 View의 속성은 사용자 또는 CollectionView가 레이아웃을 무효화 할 때까지 동일하게 유지됩니다.
레이아웃 객체의 invalidateLayout 메서드를 호출하면 preparationLayout 메서드에 대한 새로운 호출부터 시작하여 레이아웃 프로세스가 다시 시작됩니다.
CollectionView는 스크롤하는 동안 레이아웃을 자동으로 무효화 할 수도 있습니다.
사용자가 내용을 스크롤하면 CollectionView는 레이아웃 객체의 shouldInvalidateLayoutForBoundsChange : 메서드를 호출하고 해당 메서드가 YES를 반환하면 레이아웃을 무효화합니다.
참고 : invalidateLayout 메서드를 호출해도 레이아웃 업데이트 프로세스가 즉시 시작되지는 않습니다.
이 방법은 레이아웃이 데이터와 일치하지 않으며 업데이트가 필요한 것으로 표시합니다.
다음 View 업데이트 주기 동안 CollectionView는 레이아웃이 더티인지 확인하고 더러워진 경우 업데이트합니다.
실제로 매번 즉시 레이아웃 업데이트를 트리거하지 않고 invalidateLayout 메소드를 여러 번 빠르게 연속해서 호출 할 수 있습니다.
Creating Layout Attributes
레이아웃이 책임을 지는 속성 객체는 UICollectionViewLayoutAttributes 클래스의 인스턴스입니다.
레이아웃 정보는 즉시 계산되지 않고 캐시되고 참조 될 수 있기 때문입니다.
모든 속성을 계산하는 데 드는 비용이 앱에서 캐싱하는 것의 이점보다 큰 경우 요청이 있을 때 속성을 만드는 것이 쉽습니다.
캐싱하는 이점보다 새 인스턴스를 생성할 때 UICollectionViewLayoutAttributes 클래스의 다음 클래스 메서드 중 하나를 사용하십시오.
LayoutAttributesForCellWithIndexPath :
LayoutAttributesForSupplementaryViewOfKind : withIndexPath :
LayoutAttributesForDecorationViewOfKind : withIndexPath :
우리가 앞으로 다룰 예제입니다.
Subclassing UICollectionViewLayoutAttributes
우리는 앞으로 아래 두 Layout Attributes 를 subclassing 할 것입니다.
UICollectionViewLayoutAttributes 를 subclassing 하면 isEqual: 메서드를 재정의하여 속성 값을 비교해야합니다.
IOS 7 이상에서 컬렉션 뷰는 해당 속성이 변경되지 않은 경우 레이아웃 속성을 적용하지 않습니다.
final class StickyLayoutAttributes: UICollectionViewLayoutAttributes override func isEqual(_ object: Any?) -> Bool { } |
LayoutAttributes은 CollectionView로 복사 될 수 있으므로 사용자 정의 속성을 서브 클래스의 새 인스턴스에 복사하는 데 적합한 방법을 구현하여 서브 클래스가 NSCopying 프로토콜을 준수하는지 확인하십시오.
UICollectionReusableView 객체는 사용자 정의 속성을 적용 할 수 있도록 apply (_ :) 메소드를 구현해야합니다.
IsEqual: 메소드를 사용하여 이전 속성 오브젝트와 새 속성 오브젝트를 비교하여 속성이 변경되었는지 여부를 판별합니다.
만약 사용자 정의 속성이 모두 같으면 super를 호출하고 구현이 끝날 때 결과 값을 반환하십시오.
마무리
길었던 Creatinng Custom Layout 의 이론편이 끝났습니다.
이제 바로 실전편으로 가서 실제 예제를 확인해 봅시다!
참조:
https://devmjun.github.io/archive/UICollectionView-doc-1
https://www.raywenderlich.com/392-uicollectionview-custom-layout-tutorial-pinterest
https://www.raywenderlich.com/527-custom-uicollectionviewlayout-tutorial-with-parallax
https://developer.apple.com/documentation/uikit/uicollectionview/customizing_collection_view_layouts
https://developer.apple.com/documentation/uikit/uicollectionviewlayoutattributes