티스토리 뷰
위와 같은 CollectionView를 Storyboard 없이 코드를 사용해서 구현해보자.
Autolayout은 SnapKit을 사용했다.
1. UICollectionViewCell 생성
먼저 CollectionView에 사용할 UICollectionViewCell을 만들었다.
CollectionViewCell.swift
//
// CollectionViewCell.swift
// CollectionView_Programmatically_Tutorial
import UIKit
import SnapKit
class CollectionViewCell: UICollectionViewCell {
// Reuse Identifier
static let cellId = "CollectionCellId"
// Set Cell Elements
let foodImage: UIImageView = {
let image = UIImageView()
image.image = UIImage(named: "image1")
image.contentMode = .scaleAspectFit
return image
}()
let foodLabel: UILabel = {
let label = UILabel()
label.font = UIFont.systemFont(ofSize: 16)
label.text = "Goulash"
label.textAlignment = .center
return label
}()
// Init
override init(frame: CGRect) {
super.init(frame: .zero)
setUpCell()
setUpLayout()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension CollectionViewCell {
func setUpCell() {
addSubview(foodImage)
addSubview(foodLabel)
}
func setUpLayout() {
// Autolayout with SnapKit
foodImage.snp.makeConstraints { make in
make.top.equalToSuperview().offset(16)
make.leading.equalToSuperview().offset(32)
make.bottom.equalToSuperview().offset(-32)
make.trailing.equalToSuperview().offset(-32)
}
foodLabel.snp.makeConstraints { make in
make.top.equalTo(foodImage.snp.bottom).offset(-16)
make.leading.trailing.equalTo(foodImage)
}
}
}
CollectionViewCell에 UIImageView와 UILabel을 각각 foodImage, foodLabel이라는 이름으로 생성해주었다.
setUpCell()에서는 위에서 foodImage와 foodLabel을 SubView로 추가.
setUpLayout()에서는 SnapKit을 이용해 layout을 설정해 주었다.
다음으로 ViewController.swift에서 collectionView를 만든 후 그 안에 collectionViewCell을 넣어보자.
2. Data 배열 생성 & Asset에 Image 추가
ViewController.swift
데이터 배열을 하나 만들어 주었다.
var data = ["Goulash", "Maple Syrup", "Nasi Goreng", "Paella", "Pasta", "Spring rolls",
"Goulash", "Maple Syrup", "Nasi Goreng", "Paella", "Pasta", "Spring rolls",
"Goulash", "Maple Syrup", "Nasi Goreng", "Paella", "Pasta", "Spring rolls"]
Assets 이미지도 추가해 주었다.
3. UICollectionView 생성
collectionView 생성
var collectionView: UICollectionView!
- setUpCollectionView()
collectionView에 대한 설정을 해주자.
func setUpCollectionView() {
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.scrollDirection = .horizontal // Scroll 방향 설정
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
// Delegate, DataSource, Register Cell
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: CollectionViewCell.cellId)
//Background Color
collectionView.backgroundColor = .blue
}
CollectionView는 TableView와 다르게 layout을 추가해 주어야 한다. 그렇지 않을 경우 에러가 발생한다.
layout이라는 UICollectionViewFlowLayout 객체를 생성하고 필요한 속성을 추가해주자.
위에서는 sectionInset을 전부 0으로 해서 collectionView와 section이 딱 맞게 해 줬고
scrollDirection을 .horizontal로 변경해 주었다.
추가로 cell의 size와 cell 간의 간격 등을 조절할 수 있다. 공식 홈페이지를 참고하자.
https://developer.apple.com/documentation/uikit/uicollectionviewflowlayout
collectionView에 frame과 만들어둔 layout을 추가해주자.
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
setUpCollectionView()에서 추가로 UICollectionViewDelegate, UICollectionViewDataSource 프로토콜을 채택해 주었고
위에서 미리 만들어 두었던 CollectionViewCell을 등록해 주었다.
-setUpView() & setUpLayout()
이제 만들었던 collectionView를 Subview로 추가해주고
Snapkit을 이용해 layout을 추가해주었다.
func setUpView() {
view.addSubview(collectionView)
}
func setUpLayout() {
collectionView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(40)
make.leading.trailing.equalToSuperview()
make.height.equalTo(160)
}
}
setUpCollectionView(), setUpView(), setUpLayout() 모두 viewDidLoad()에서 실행해 주는 것을 잊지 말자.
override func viewDidLoad() {
super.viewDidLoad()
setUpCollectionView()
setUpView()
setUpLayout()
}
4. UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewFlowLayout
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Did Selected Item At : \(indexPath.row)")
}
}
didSelectItemAt 메소드를 이용해 cell을 선택하면 몇 번째 cell이 선택됐는지 print 하도록 했다.
extension ViewController: UICollectionViewDataSource {
// Section의 Item 개수 설정
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
// cell 설정
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionViewCell.cellId, for: indexPath) as! CollectionViewCell
cell.backgroundColor = .systemGreen
let imageNumber: Int = indexPath.row % 6 + 1
cell.foodImage.image = UIImage(named: "image\(imageNumber)")
cell.foodLabel.text = data[indexPath.row]
return cell
}
}
UICollectionViewDataSource를 채택하면 numberOfItemInSection, cellForItemAt 이 두 메서드는 필수로 구현해야 한다.
numberOfItemInSection은 아이템의 개수, cellForItemAt 은 cell을 생성한다.
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 160, height: 200)
}
}
UICollectionViewDelegateFlowLayout에서는 아이템의 사이즈를 설정해 주었다.
위의 collectionView를 생성할 때 추가했던 UICollectionViewFlowLayout 객체인 layout에서도 item의 사이즈나 간격을 설정할 수 있지만 UICollectionViewDelegateFlowLayout에서도 설정 가능하다.
ViewController.swift 전체 코드
//
// ViewController.swift
// CollectionView_Programmatically_Tutorial
import UIKit
import SnapKit
class ViewController: UIViewController {
var collectionView: UICollectionView!
var data = ["Goulash", "Maple Syrup", "Nasi Goreng", "Paella", "Pasta", "Spring rolls","Goulash", "Maple Syrup", "Nasi Goreng", "Paella", "Pasta", "Spring rolls","Goulash", "Maple Syrup", "Nasi Goreng", "Paella", "Pasta", "Spring rolls"]
override func viewDidLoad() {
super.viewDidLoad()
setUpCollectionView()
setUpView()
setUpLayout()
}
}
extension ViewController {
func setUpCollectionView() {
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.scrollDirection = .horizontal // Scroll 방향 설정
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
// Delegate, DataSource, Register Cell
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: CollectionViewCell.cellId)
//Background Color
collectionView.backgroundColor = .blue
}
func setUpView() {
view.addSubview(collectionView)
}
func setUpLayout() {
collectionView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(40)
make.leading.trailing.equalToSuperview()
make.height.equalTo(160)
}
}
}
extension ViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Did Selected Item At : \(indexPath.row)")
}
}
extension ViewController: UICollectionViewDataSource {
// Section의 Item 개수 설정
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
// cell 설정
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CollectionViewCell.cellId, for: indexPath) as! CollectionViewCell
cell.backgroundColor = .systemGreen
let imageNumber: Int = indexPath.row % 6 + 1
cell.foodImage.image = UIImage(named: "image\(imageNumber)")
cell.foodLabel.text = data[indexPath.row]
return cell
}
}
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 160, height: 200)
}
}
실행해보면 다음과 같이 잘 작동한다.
'iOS' 카테고리의 다른 글
iOS) UIDatePicker - 2 / Count Down Timer 생성 (0) | 2022.07.26 |
---|---|
iOS) UIDatePicker - 1 (0) | 2022.07.24 |
iOS) Error "UICollectionView must be initialized with a non-nil layout parameter" (0) | 2022.07.19 |
iOS) CAGradientLayer (Gradient View) (0) | 2022.07.12 |
iOS) SnapKit을 이용해 AutoLayout 구현하기 (0) | 2022.07.09 |
- Total
- Today
- Yesterday
- Carousel Effect
- BOJ 10866
- Gradient View
- UICollectionView banner
- BOJ 1935
- Algorithm
- CAGradientLayer
- 1406 에디터
- BOJ 10799
- Card CollectionVIew
- crud
- BOJ 10809
- BOJ 17298
- git
- sheetPresentationController
- autolayout
- 요시푸스
- BOJ 10820
- swift
- ios
- 2023 회고
- bottom sheet
- Stack
- BOJ 10808
- UICollectionView Error
- Sheet Height
- BOJ 17413
- github
- Custom Detent
- NaverMaps
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |