[iOS] UICollectionView - 2

Yong-Tae Kwon·2021년 3월 3일
0

ios

목록 보기
2/2

4. Collection View의 Interaction

var delegate: UICollectionViewDelegate?

  • collection view의 delgate object.
  • 컬렉션 요소와 사용자간 상호작용을 처리한다.
  • UICollectionViewDelegate: collection view의 동작을 관리하는 메소드들의 protocol이다.
  • 모든 메소드들은 optional이다.
  • 공통적으로 delegate에게 알려주는 것은 Void / delegate이 return해 주는 것은 non-Void라고 생각하자.

Selection

  1. func collectionView(UICollectionView, shouldSelectItemsAt: Set<IndexPath>) -> Set<IndexPath>
    • item이 select 가능한지
    • 선택 가능한 item들의 set을 return
  2. func collectionView(UICollectionView, didSelectItemsAt: Set<IndexPath>)
    • item(들)이 선택되었을 때 delegate에게 알린다.
  3. func collectionView(UICollectionView, shouldDeselectItemsAt: Set<IndexPath>) -> Set<IndexPath>
    • item이 선택해제 가능한지
    • 선택해제 가능한 item들의 set을 return
  4. func collectionView(UICollectionView, didDeselectItemsAt: Set<IndexPath>)
    • item(들)이 선택 해제되었을 때 delegate에게 알린다.
  5. func collectionView(UICollectionView, shouldBeginMultipleSelectionInteractionAt: IndexPath) -> Bool
    • two-finger pan gesture를 사용해서 여러 item을 선택할 수 있는지 여부를 return
  6. func collectionView(UICollectionView, didBeginMultipleSelectionInteractionAt: IndexPath)
    • 사용자가 two-finger pan gesture 사용을 시작할 때 delegate에게 알린다.
  7. func collectionViewDidEndMultipleSelectionInteraction(UICollectionView)
    • 사용지가 two-finger pan gesture 사용을 끝냈을 때 delegate에게 알린다.

Item Highlight

  1. func collectionView(UICollectionView, shouldHighlightItemAt: IndexPath) -> Bool
    • item이 highlight되어야하는지 delegate에게 return한다.
  2. func collectionView(UICollectionView, didHighlightItemAt: IndexPath)
    • 어떤 indexpath에 있는 item이 highlight되었음을 deleagte에게 알린다.
  3. func collectionView(UICollectionView, didUnhighlightItemAt: IndexPath)
    • 어떤 indexpath에 있는 item이 highlight 제거되었음을 delegate에게 알린다.

Item의 추가/삭제 tracking

  1. func collectionView(UICollectionView, willDisplay: UICollectionViewCell, forItemAt: IndexPath)
    • collection view에 어떤 cell이 곧 추가될 것임을 delegate에게 알린다.
  2. func collectionView(UICollectionView, willDisplaySupplementaryView: UICollectionReusableView, forElementKind: String, at: IndexPath)
    • collection view에 어떤 supplementary view가 곧 추가될 것임을 delegate에게 알린다.
  3. func collectionView(UICollectionView, didEndDisplaying: UICollectionViewCell, forItemAt: IndexPath)
    • collection view에 어떤 cell이 제거되었음을 delegate에게 알린다.
  4. func collectionView(UICollectionView, didEndDisplayingSupplementaryView: UICollectionReusableView, forElementOfKind: String, at: IndexPath)
    • collection view에 어떤 supplementary view가 제거되었음을 delegate에게 알린다.

Layout 변경 handling

  1. func collectionView(UICollectionView, transitionLayoutForOldLayout: UICollectionViewLayout, newLayout: UICollectionViewLayout) -> UICollectionViewTransitionLayout
  2. func collectionView(UICollectionView, targetContentOffsetForProposedContentOffset: CGPoint) -> CGPoint
  3. func collectionView(UICollectionView, targetIndexPathForMoveFromItemAt: IndexPath, toProposedIndexPath: IndexPath) -> IndexPath

Focus handling

  1. func collectionView(UICollectionView, canFocusItemAt: IndexPath) -> Bool
  2. func indexPathForPreferredFocusedView(in: UICollectionView) -> IndexPath?
  3. func collectionView(UICollectionView, shouldUpdateFocusIn: UICollectionViewFocusUpdateContext) -> Bool
  4. func collectionView(UICollectionView, didUpdateFocusIn: UICollectionViewFocusUpdateContext, with: UIFocusAnimationCoordinator)

5. Collection View Layout

var collectionViewLayout: UICollectionViewLayout { get set }

  • 이 속성에 새로운 layout객체를 할당해 새로운 layout을 collection view의 item에 적용시킬 수 있다.
  • layout 객체는 UICollectionViewLayout class를 상속해야한다.
  1. func setCollectionViewLayout(_ layout: UICollectionViewLayout, animated: Bool)
  2. func setCollectionViewLayout(_ layout: UICollectionViewLayout, animated: Bool, completion: ((Bool) -> Void)? = nil)
  • 위 두 메소드를 활용하면 layout Object를 변경해줄 수 있는데, 직접 collectionViewLayout이라는 인스턴스에 할당하는 것과 차이는 변화를 animating 해줄 수 있다는 것이다.
  1. func startInteractiveTransition(to: UICollectionViewLayout, completion: UICollectionView.LayoutInteractiveTransitionCompletion?) -> UICollectionViewTransitionLayout
  • 사용자의 interaction (touch event, gesture 등)에 따라서 변경할 layout Object를 설정한다.
  1. func finishInteractiveTransition()
  2. func cancelInteractiveTransition()
  • 이 메소드를 호출해서 Transition을 중단한다. (혹은 끝낸다.)

1) class UICollectionViewLayout

  • layout객체는 collection view에서 item의 눈에 보이는 상태와 위치에 대한 정보를 제공한다.
    - view를 생성해주는 것이 아니라 view를 위한 layout를 제공하는 객체이다.
    - view를 생성하는 것은 view의 data source에 의해 이루어짐.
    - layout 객체는 요소들 간의 거리/위치/크기 등의 정보를 제공
    - Collection View의 Layout은 크게 세 가지 다른 종류의 요소를 가진다.
    1. Collection View Cells
    2. Supplement View: Cell을 제외한 (Header/Footer처럼) Cell은 아닌데 추가정보를 보여줘야하는 곳
    3. Decoration View: Cell이나 Supplement View와는 달리 실제 데이터를 가지고 있지는 않지만 just 장식용으로 보여주어야 할 View
  1. class UICollectionViewFlowLayout: UICollectionViewLayout

    • layout을 지정해주지 않았을 때는 UICollectionViewFlowLayout을 default로 가진다.

    • 만약 default인 flow layout을 layout object로 가진다고 했을때,
      protocol UICollectionViewDelegateFlowLayout 프로토콜의 메소드들이 아이템(cell, supplement view 등)의 크기나 아이템 간의 공간 등을 정의해준다.
      예시로, 다음과 같은 메소드들이 있다.
      - func collectionView(UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) -> CGSize : item cell의 크기를 정의하는 메소드
      - func collectionView(UICollectionView, layout: UICollectionViewLayout, insetForSectionAt: Int) -> UIEdgeInsets : 특정 section의 view들의 margin을 정의하는 메소드 (cell간의 간격 / footer, header 간의 간격 등)

    • Flow Layout이 어떻게 생기는가?
      1. layout객체 작성
      2. cell width/height 결정 (필수!)
      - cell 간격 결정 (필요할 경우)
      - header/footer 사이즈, 간격 결정(필요할 경우)
      3. layout 스크롤 방향 결정
      * item하나의 크기를 결정하는 방법.
      1. (모든 item의 크기가 같은 경우) Layout Object의 itemSize 속성을 지정한다.
      2. (item마다 크기가 다른경우) collectionView(_:layout:sizeForItemAt:) method를 호출한다.
      3. estimatedItemSize 속성을 활용한다. (iOS 8~ 비추!)

  2. class UICollectionViewTransitionLayout: UICollectionViewLayout

2) Customizing Collection View Layouts

  • UICollectionViewLayout을 Custom해서 (상속받아서)새로운 커스텀 layout class를 만드는 방법 두 가지
    1. storyboard에서 collection view의 layout class를 변경한다.
    2. collectionView.collectionViewLayout = MyCustomLayout() 코드로 할당해준다.

  • UICollectionViewLayout의 Subclass는 아래 설명의 메소드들을 구현해야한다.

Layout Process에 대한 간략한 설명

  • Collection View <-> Layout Object (collectionViewLayout) 간의 상호작용
    1. prepare Layout
    - func prepare(): Layout작업이 수행되려고 할 때마다 이 method가 호출된다. collection view의 크기, item 위치 등을 결정하기 위해 필요한 선 연산을 수행한다.
    - cache를 활용해서 attribute만드는 작업을 불필요하게 반복하지 않는다.
    2. contentSize
    - var collectionViewContentSize: CGSize { get }: prepare에서 수행한 연산을 기반으로 collection view 컨텐츠의 전체 크기를 리턴한다.
    - 계산된 크기가 실제 화면 크기보다 크다면 스크롤이 가능하다.
    3. layoutAttributes
    - func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?: 특정 사각형 범위의 모든 cell과 view의 layout atrribute를 리턴한다. (이 사각형 범위는 보여지는 화면의 크기와 같을 수도 있지만 아닐 수도 있다.)
    - layoutAttributesForItem(at: indexPath): 특정 indexPath의 모든 cell과 view의 layout atrribute를 리턴한다.
    - layoutAttributesForSupplementaryView(ofKind:at:) (supplementary view 사용 시)
    - layoutAttributesForDecorationView(ofKind:at:) (decoration view 사용 시)
    4. invalid Layout
    - shouldInvalidateLayout(forBoundsChange:): bound가 바뀌어서 layout이 update가 필요한지 리턴한다.
    - invalidLayout(): 명시적으로 layout을 update하라고 요청한다.

UICollectionViewLayoutAttributes

  • 개별적인 cell의 위치와 크기를 저장할 attribute 배열
  • 일반적으로 현재 화면에서 보여지는 사각형의 크기안에 들어오는 item들의 크기.위치 정보를 저장해 리턴하게 된다.
  • 더 공부하기

6. Reload Content

  • Reload Item: item object를 return한 뒤에 data가 변경되었다면, 아래 method들을 호출하여 모든 item object를 reload한다.
  • item이 insert/delete되는 animation block들 중간에 reload 메소드들을 호출해서는 안된다. item Insertion이나 Deletion은 자동으로 적절하게 collection의 data를 update시켜주기 때문이다.
  • methods
    - func reloadData()
    - func reloadSections(IndexSet)
    - func reloadItems(at: [IndexPath])

7. ReOrdering Items

  • Reorder: data source에 의해 구현된 collection view를 사용자의 interaction을 통해 reorder 하는 경우 사용한다.

8. Insert / Move / Delete

  • item을 indexpath로 insert/move/delete하는 것이 가능하다.
    - func insertItems(at: [IndexPath])
    - func moveItem(at: IndexPath, to: IndexPath)
    - func deleteItems(at: [IndexPath])
  • section을 indexpath로 inser/move/delete하는 것이 가능하다.
    - func insertSections(IndexSet)
    - func moveSection(Int, toSection: Int)
    - func deleteSections(IndexSet)
  • 의문: reload Data 해주는 방식과 어떤 차별점이 있는지? 오히려 더 로직이 복잡해지는 것이 아닌가? reload하는 것이 cost가 크기 때문일?
  • func performBatchUpdates((() -> Void)?, completion: ((Bool) -> Void)?)
    - Collection View에 여러 변경 사항을 한꺼번에 animate하게 만든다.
    - 주의: deletion이 insertion보다 항상 먼저 일어남! (잘못된 접근이 발생할 수 있다)
profile
To Infinity, and Beyond!

0개의 댓글