UICollectionView는 UITableView와 달리, 다양한 형태의 아이템 표시와 사용자 정의 레이아웃을 제공하여 개발자들에게 큰 유연성을 제공한다. 제공하는 레이아웃중 많이 사용되는 CollectionViewFlowLayout에 대해 알아보자
UICollectionViewFlowLayout는 UICollectionView의 아이템들을 어떻게 배치할지 결정하는 레이아웃 중 하나다. 다양한 속성들을 알아보도록 하자.
Flow Layout은 UICollectionView에 자주 사용되는 레이아웃이다. 이름대로 자연스럽게 흐르듯 아이템들을 순차적으로 배치하며, 한 행의 공간이 모두 채워지면 다음 행으로 넘어간다. (선형 배치)
UICollectionViewFlowLayout을 사용하여 아이템의 크기, 행 간격, 섹션 여백 등 다양한 레이아웃 속성을 지정할 수 있다. 유연하고 동적인 인터페이스를 만들 수 있다.
주로 그리드 형태에 많이 사용하지만 다양한 형태로 표현하는것도 가능
레이아웃의 스크롤 방향은 기본적으로 세로 방향이다, footer와 header의 크기는 기본적으로 0이기때문에 화면에 나타나지 않는다. 사용하기 위해서는 0보다 큰 수치로 설정해야 한다.
UICollectionView에서 아이템들의 크기를 지정하는 방법은 크게 세 가지가 있다.
동일한 크기의 아이템: itemSize속성을 사용하여 모든 셀의 크기를 지정한다. 이 방법은 모든 셀이 동일한 크기일 때 가장 효과적으로 사용할 수 있다.
다양한 크기의 아이템: UICollectionViewDelegateFlowLayout의 collectionView:layout:sizeForItemAtIndexPath메서드를 구현 하여 각 셀의 크기를 지정할 수 있다. 제공된 인덱스에 따라 해당 아이템의 크기를 반환한다. 동일한 라인에 있는 아이템들은 수직으로 중앙에 배치되며, 해당 라인의 전체 높이나 너비는 그 라인에서 가장 큰 아이템의 크기에 의해 결정된다.
func collectionView(UICollectionView, layout: UICollectionViewLayout, sizeForItemAt: IndexPath) -> CGSize
동일한 라인에 있는 아이템들 사이, 그리고 연속되는 라인 사이의 최소 간격을 지정할 수 있다.
// 아이템 간의 최소 간격을 정의한다.
var minimumInteritemSpacing: CGFloat
// 라인 간의 최소 간격을 정의한다.
var minimumLineSpacing: CGFloat
아이템과 라인 간의 간격은 섹션별로 다를 수 있다.minimumLineSpacing과 minimumInteritemSpacing 속성을 사용하거나, collectionView:layout:minimumLineSpacingForSectionAtIndex: 및 collectionView:layout:minimumInteritemSpacingForSectionAtIndex: 메서드를 통해 동적으로 지정할 수 있다고 한다.
그런데 속성을 통해 지정하는것과 델리게이트 메서드를 통해 지정하는 것의 차이가 뭘까? 동적으로 지정할 수 있다는건 어떤 이유일까?
minimumLineSpacing과 minimumInteritemSpacing 속성을 사용하면, 모든 섹션에 대해 동일한 간격이 설정된다, 반면 델리게이트 메서드들을 사용하면 인덱스로 접근이 가능하여 개별적으로 다른 간격을 지정할 수 있다. 그렇기 때문에 각 섹션마다 다른 값을 설정할수 있기 때문에 동적이라고 표현하고 있다.
Section Inset응 사용하여 콘텐츠의 여백을 설정할 수 있다.
SectionInset 속성은 콘텐츠 여백을 조절하는 데 사용된다. 여기서 여백이란, 셀과 섹션의 헤더 또는 푸터, 그리고 콘텐츠의 양쪽 여백을 의미한다.
여백은 셀을 배치할수 있는 공간을 줄이므로, 한 라인에 배치될 수 있는 셀의 수를 제한하는데 사용 가능하다.
아래의 이미지는 세로로 스크롤되는 플로우 레이아웃에서 여백이 콘텐츠에 어떻게 여향을 미치는지 보여준다.
위의 설명에서 UICollectionViewDelegateFlowLayout프로토콜 메서드에 대한 내용들을 언급했었다. 이 프로토콜은 UICollectionViewFlowLayout객체와 상호작용하여 레이아웃을 조정할 수 있는 메서드가 정의되어 있다. 주요 메서드들을 알아보자
// 지정된 셀의 크기를 변환하는 메서드
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
// 지정된 섹션의 여백을 반환하는 메서드
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
insetForSectionAt section: Int) -> UIEdgeInsets
// 지정된 섹션의 행 사이 간격 최소 간격을 반환하는 메서드
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumLineSpacingForSectionAt section: Int) -> CGFloat
// 지정된 섹션의 셀 사이의 최소간격을 반환하는 메서드
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
minimumInteritemSpacingForSectionAt section: Int) -> CGFloat
// 지정된 섹션의 헤더뷰의 크기를 반환하는 메서드, 크기를 지정하지 않으면 화면에 보이지 않는다.
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
referenceSizeForHeaderInSection section: Int) -> CGSize
// 지정된 섹션의 푸터뷰의 크기를 반환하는 메서드. 크기를 지정하지 않으면 화면에 보이지 않는다.
optional func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
referenceSizeForFooterInSection section: Int) -> CGSize
아이템들을 어떻게 배치할지 설정할 수 있는 레이아웃 중 하나인 UICollectionViewFlowLayout을 알아봤다. 여러 속성과 UICollectionViewDelegateFlowLayout를 통해 간격들을 설정할 수 있다. 아직 직접 사용해보지 않아서 헷갈리는 부분이 있다, 바로 다음글에서 어떻게 사용하는지 구현해보겠다.
참고: 애플 공식문서, 부스트캠프 iOS프로그래밍