오늘은 컬렉션뷰에 대해 이야기 해보고자 합니다. 글에 엉성한 부분이 많습니다. 앞으로 더 공부하면서 다듬고 수정해 나갈 예정입니다. 잘못된 부분은 피드백 주시면 적극 수용하도록 하겠습니다.
Collection View란??
컬렉션 뷰(Collection View)란 중첩된 뷰?를 자유롭게 구성가능한 레이아웃을 이용해 보여주는 것??? 이라고 하는 거 같습니다... 오역 죄송합니다. 여튼 밑에 사진을 보시면 대충 이해가 오실겁니다. 우리가 사진 앱을사용할 때 n x n의 형태로 화면이 구성된 것을 볼 수 있는데 이러한 화면을 우리는 컬렉션 뷰를 사용해 만들 수 있습니다.
만드는 법
먼저 다음과 같이 컬렉션 뷰 컨트롤러(Collection View Controller)를 스토리보드 상에 만들어줍니다. 저 정사각형을 컬렉션 뷰 셀(Collection View Cell)이라고 하는데 우리가 n X n으로 띄워줄 화면을 의미합니다. 그 후 안에 레이아웃을 잡아 적당하게 조절해줍니다.
그런 다음 컬렉션 뷰 셀, 컬렉션 뷰 컨트롤러 파일을 만들고 커스텀 클래스로 지정해줍니다. 그리고 마지막으로 컬렉션 뷰의 identifier를 반드시!!! 지정해줘야합니다.(깜빡하기 매우 쉬움!!!)
그 다음은 함수를 적용해줍니다. 컬렉션 뷰를 구성할 때 필수인 함수는 collectionView(_:cellForItemAt:)과 collectionView(_:numberOfItemsInSection:) 두 가지 입니다.
셀이 컬렉션뷰안의 특정 아이템들과 일치할 수 있도록 데이터 소스 객체에게 요청한다?... 쉽게 말하자면 컬렉션 뷰의 지정된 위치에 표시할 셀을 요청하는 메소드 입니다. 'Collection View Cell 에서 정보들을 가져오도록 요청해준다'라고 보시면 되겠습니다.
이 함수는 말그대로 몇 개의 아이템을 하나의 섹션에 가질 것인가를 정해주는 함수입니다. 이걸 100개로 나타내주면 100개의 셀이 나타나겠죠? 그럼 한 번 코드로 살펴봅시다.
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
cell.backgroundColor = .blue
return cell
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 100
}
cellForItemAt함수를 사용해서 컬렉션 뷰 셀의 아이템을 셀로 사용하겠다 선언해주었습니다. numberOFItemsInSection으로 100개의 아이템을 섹션에 나타내도록 하였습니다. 그리고 실행하면 이와 같은 화면이 나옵니다.
우리가 원하는 화면과는 조금 거리가 먼? 화면이 나타났습니다. 우리가 이미지 뷰의 크기는 완전히 무시되고 100개의 뷰가 한 화면에 나오게 되었습니다. 이러한 부분을 해결하려면 우리는 셀에대해 레이아웃을 설정 해주어야 합니다. 몇 가지 방법이 있지만 우리는 UICollectionViewFlowLayout을 사용해 보겠습니다.
flow layout은 collection view layout을 상속받는 객체로 격자 형태로 레이아웃을 생성합니다. 최대한 많은 셀을 포함합니다. 이 layout은 행 또는 열의 방향(스크롤 방향에 따라 다름)으로 최대한 많은 셀을 배치합니다. 다만, 셀의 사이즈는 같을수도 다를 수도 있습니다.
flow layout은 아이템, 헤더, 푸터들의 사이즈를 결정하기 위해 컬렉션뷰의 딜리게이트와 함께 동작합니다. 이 딜리게이트가 바로 UICollectionViewDelegateFlowLayout인데 이 프로토콜을 반드시 채택해줘야 합니다! 이 딜리게이트를 사용하면 layout 정보를 다양하게 적용 가능합니다. (ex. 각각의 다른 사이즈의 아이템들)r
위 그림과 같이 컬렉션 뷰는 플로우 레이아웃을 통해 어떻게 아이템을 보여줄지 정하고 이와 관련된 데이터를 델리게이트, 데이트소스를 통해 관리합니다.
위의 두 그림을 보시면 알겠지만 수평, 수직 옵션에 따라 최대한 많은 셀을 넣으려고 하는 것을 볼 수 있습니다 .또한 수직 스크롤의 경우 화살표 방향(왼쪽 > 오른쪽)으로 인덱싱이 되는 반면 수평스크롤의 경우 화살표 방향(위에서 아래로) 이루어집니다.
FlowLayout의 사용법?은 이러합니다.
- 플로우 레이아웃의 인스턴스화
- 셀의 사이즈 지정
- 스크롤 방향 지정(수직 or 수평)
- 셀의 간격지정
- 셀과 행사이의 간격지정(minimumLineSpacing, minimumInteritemSpacing
여기서 주의할 점이 하나 있습니다. 최소간격을 설정하는데 있어 모든 셀의 크기가 동일하다면 다음 그림과 같이 문제가 없습니다.
하지만 가각의 셀 크기가 다른 경우 셀간의 최소간격은 셀간의 실제간격과 다를 수 있습니다.
추가적으로 섹션자체에 인셋(간격)을 주는 것도 가능합니다.
이를 적용해 코드로 한 번 나타내 보겠습니다.
override func viewDidLoad() {
super.viewDidLoad()
let layout = UICollectionViewFlowLayout()
let space: CGFloat = 8
let width = UIScreen.main.bounds.width - (space * 4)
layout.itemSize = CGSize(width: width / 3, height: width / 3)
layout.scrollDirection = .vertical
// 섹션과의 인셋(간격)주는 함수
layout.sectionInset = UIEdgeInsets(top: space, left: space, bottom: space, right: space)
layout.minimumLineSpacing = space
layout.minimumInteritemSpacing = space
collectionView.collectionViewLayout = layout
}
UIScreen을 활용해 간격을 빼주고 가져갈 수 있는 width를 정해줬습니다. 그 후에 이 width를 활용해 실제 셀의 너비와 너비를 3으로 나눠가졌습니다. 그러면 세로 방향으로 3개씩 셀을 가져갈 수 있게 됩니다.
참고
https://developer.apple.com/documentation/uikit/uicollectionview
https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout
www.edwith.org/boostcourse-ios/lecture/16906/
'iOS' 카테고리의 다른 글
[iOS] User Notification Ⅰ. 로컬 알림(Local Notification) (0) | 2022.07.29 |
---|---|
[iOS] WKWebView (0) | 2022.07.28 |
[iOS] TableViewController - Custom Table View Cell (0) | 2022.07.19 |
[iOS] TableViewController - System Cell (0) | 2022.07.18 |
[iOS] 생명주기 + AppDelegate & SceneDelegate (0) | 2022.07.17 |