์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
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 | 29 |
30 |
- Lv2
- arkit
- Xcode
- designpattern
- SwiftUI
- tableView
- swift
- Swfit
- ํ๋ก๊ทธ๋๋จธ์ค
- RxSwift
- BOJ
- MVVM
- ๋ฐฑ์ค
- ios
- XCTest
- node.js
- reactorkit
- realm
- ํจ์คํธ์บ ํผ์ค
- Flutter
- rxcocoa
- CollectionView
- UIKit
- Kuring
- combine
- visionOS
- raywenderlich
- BFS
- SnapKit
- TCA
- Today
- Total
lgvv98
ch17 ๋์ ScrollView Guide! ์ํ์ข์ฐ!! ๋ณธ๋ฌธ
ch17 ๋์ ScrollView Guide! ์ํ์ข์ฐ!!
๐ฅ ์บ๋ฟ๋งจ 2021. 6. 29. 23:59โ ์ด๋ฒ์๊ฐ์๋ ์คํฌ๋กค ๋ทฐ์ ๋ํด์ ์์๋ณด์.
์ฌ์ค ์์ ์ ์คํฌ๋กค ๋ทฐ๋ฅผ ๊ธํ๊ฒ ์ฌ์ฉํ ์ผ์ด ์์ด์ ๊ตฌ๊ธ๋งํด์ ์ฌ์ฉํ๋ ์ ์ด ์๋๋ฐ, ๊ทธ๋ ์ ํํ๊ฒ ์ดํดํ ๊ฒ์ด ์๋๋ผ์ ๋ค๋ฅธ๊ณณ์ ์ ์ฉํ ๋ ์๋์๋ ๊ธฐ์ต์ด... ๊ทธ๋ผ ์๋ฌดํผ ๋ค์ ๊ณต๋ถํด๋ณด๋๋ก ํ ๊น?
(๋ค์ด๊ฐ๊ธฐ ์์...)
๊ฐ์์์๋ Nested ScrollView(๋ค์คํฐ๋ ์คํฌ๋กค ๋ทฐ) ๋ผ๋ ์ฉ์ด๋ฅผ ๋ง์ด ์ฌ์ฉํ๋๋ฐ, ๋ค์คํฐ๋ ์คํฌ๋กค ๋ทฐ๋, ์ด์ค ์คํฌ๋กค ๋ทฐ๋ผ๋ ์๋ฏธ๋ก, ์คํฌ๋กค ๋ทฐ์์ ์คํฌ๋กค ๋ทฐ๋ฅผ ํ๋ ๋ ์ถ๊ฐํ ๊ฒ์ ์๋ฏธํ๋ค. ์คํฌ๋กค ๋ทฐ๊ฐ ์ฆ, 2๊ฐ ์๋ค๊ณ ์๊ฐํ๋ฉด ํธํ ๋ฏ ํ๋ค.
โ ๋ชฉ์ฐจ
1. ์คํฌ๋กค ๋ทฐ ๊ธฐ๋ณธ ๊ฐ์ด๋ - ์ํ๋ก ์์ง์ด๊ธฐ (Vertical Scroll View)
2. ์คํฌ๋กค ๋ทฐ Advanced - ์ข์ฐ๋ก๋ ์์ง์ด๊ธฐ (Horizontal Scroll View)
โ ๊ทธ๋ผ ์ด์ ์ง์ง ์์!!
1๏ธโฃ Vertical Scroll View
์ผ๋จ ์คํ ๋ฆฌ๋ณด๋์์ ๋ทฐ ์ปจํธ๋กค๋ฌ์ ์คํฌ๋กค ๋ทฐ๋ฅผ ์ถ๊ฐํด!
๊ทธ ์ดํ์ ๋ ์ด์์์ ์ก์์ค๊ฑด๋ฐ, ๊ทธ๋ฅ ์ํ์ข์ฐ 0,0,0,0 ์ผ๋ก ์ธํ ํ๋ฉด ์๋์ ๊ทธ๋ฆผ๊ณผ ๊ฐ์ด ๋นจ๊ฐ๋ถ์ด ๋ค์ด์ค๋ ๊ฒ์ ๋ณผ ์ ์์ด.
์ด์ ์๋ ์๋ค์ด์ค๋๋ฐ ์กฐ๊ธ ์ด์ํ์ง?
์คํฌ๋กค ๋ทฐ์์๋ ์๊ธฐ ๋ทฐ ๋ง๊ณ ์ปจํ ์ธ ๋ทฐ์ ๋ํ ์ ์ฝ์กฐ๊ฑด๋ ์ค์ ํด์ค์ผ ๋นจ๊ฐ์์ด ์์ด์ง๋๊น ์ผ๋จ ๋์ด๊ฐ๋ฉด์ ๋ณด์
์ฐ๋ฆฌ๊ฐ ๋ ์ด์์๊น์ง ์ก์๋ค๋ฉด ํ์ฌ ์ด๋ฐ ์ํ์ผ๊ฑฐ์ผ.
์ผ๋จ์ ์ฐ์ธก ์คํฌ๋กค ๋ทฐ ์ชฝ์์ Content Layout Guide๋ฅผ ๊บผ์ฃผ๋๋ก ํ์.
์ผ๋จ Guide๋ฅผ ๋๋ฉด ์์ ์ฌ์ง๊ณผ ๋ค๋ฅด๊ฒ ์คํฌ๋กค ๋ทฐ์ Guide ๋๊ฐ๊ฐ ์ฌ๋ผ์ง ๊ฒ์ ๋์ผ๋ก ํ์ธํ ์ ์์ด.
์ฌ๊ธฐ๋ถํฐ ์กฐ๊ธ ํท๊ฐ๋ฆด ์๊ฐ ์์ด์ ์คํฌ๋กค ๋ทฐ ์์ ์๋ ๋ทฐ๋ฅผ ์ผ๋ฐ ๋ทฐ, ์คํฌ๋กค ๋ทฐ๋ฅผ ํฌํจํ๋ ๋ทฐ๋ฅผ ์ํผ ๋ทฐ๋ผ๊ณ ๋ถ๋ฅผ๊ฒ.
1. ๊ทธ ๋ค์์๋ ์์ ์ฌ์ง์ฒ๋ผ View(์ผ๋ฐ ๋ทฐ)๋ฅผ ์ถ๊ฐํ๊ณ ๋ ์ด์์์ ์คํฌ๋กค ๋ทฐ์ ์ผ๋ฐ ๋ทฐ๋ฅผ ์ฐ๊ฒฐํด์, leading๊ณผ top์ ์ค.
์ด์ ๋ถํฐ ์ ์ํด์ ๋ด์ผํด..!
2. โ๏ธ(์ฃผ์) ๊ทธ๋ฆฌ๊ณ ์ผ๋ฐ ๋ทฐ๋ฅผ ์ํผ๋ทฐ์ ๋ ์ด์์์ ์ฐ๊ฒฐํด์ Equal Width๋ฅผ ์ค์ ํด์ฃผ๊ณ ,
3. ๊ทธ ๋ค์์๋ ์ผ๋ฐ ๋ทฐ๋ฅผ ์๊ธฐ ์์ ์ผ๋ก ์ฐ๊ฒฐํด์ Height๋ฅผ ์ก์์ค.
(โญ๏ธ ์ด๊ฑฐ ์์ฃผ ์ค์ํ ์ญํ ์ธ๋ฐ, ์ด ํฌ๊ธฐ๋ฅผ ์กฐ์ ํ๋ฉด ์คํฌ๋กค ๋ทฐ์ ์ ์ฒด์ ์ธ ๊ธธ์ด๋ฅผ ์ค์ ํด ์ค ์ ์์ด..!)
4. ๊ทธ ๋ค์์๋ ์ผ๋ฐ ๋ทฐ๋ฅผ ๋ค์ ์คํฌ๋กค ๋ทฐ๋ก ๋ ์ด์์์ ์ฐ๊ฒฐํด์ ํธ๋ ์ผ๋ง๊ณผ ๋ฐํ ์ ์ฃผ๊ธฐ.
๊ทธ๋ผ ๊ฐ์ฅ ๊ธฐ์ด์ ์ธ ์ธํ ์ด ๋๋ -> ๋ ์ด์์ ๊ฒฝ๊ณ ์ธ ๋นจ๊ฐ์์ด ์ฌ๋ผ์ ธ!!
5. ์ผ๋ฐ ๋ทฐ๋ฅผ ์ํผ๋ทฐ์ Equal Height๋ก ์ฐ๊ฒฐํด์ฃผ๊ธฐ
๊ทธ๋ฐ๋ฐ ์ฌ๊ธฐ์ ์ผ๋ฐ ๋ทฐ์ ๊ฒฝ์ฐ์๋ ์ปจํ ์ธ ์ ์ฑ๊ฒฉ์ ๊ฐ์ ธ์ ๋์ด๊ฐ ๋ฐ๋ ์๋ ์์์?
6. ๊ทธ๋์ ์ผ๋ฐ ๋ทฐ์ ์ํผ ๋ทฐ๋ฅผ ์ฐ๊ฒฐํ ์ ์ฝ์กฐ๊ฑด์ ํด๋ฆญํด์ priority๊ฐ์ ๋ฎ๊ฒ ์์ ํด ์ค์ผํด
์ด๋ ๊ฒ ์์ ํด ์ฃผ๋ฉด ๋ผ. ์์์ ๊ฐ์ ์ค๋, ์๋๋ฉด ์ฌ๊ธฐ ์ ํด์ง ๊ฐ์ ์ค๋ ๋ผ.
โ ์ฐ์ 6๋ฒ๊น์ง ์ฌ๋ฐ๋ฅด๊ฒ ์ํํ๋ค๋ฉด ์คํฌ๋กค ๋ทฐ๋ ์ ์์ ์ผ๋ก ์๋ํ ์์ !! ์๋์๋ ๋์ผ๋ก ํ์ธํ๊ธฐ ์ํด์ ์์ฑํ ๋ถ๋ถ์ด์ผ
7. ๊ทธ ๋ค์์๋ ๋ค์๊ณผ ๊ฐ์ด imageView์ StackView๋ฅผ ์ถ๊ฐํด์ค.
8. ๋์ผ๋ก ํ์ธํ๊ธฐ ์ฌ์์ผํ๋๊น ์ด๋ฏธ์ง ๋ทฐ์๋ ์ด๋ก์ ๋ฐฐ๊ฒฝ์ ์คํ๋ทฐ์๋ ๋ทฐ๋ฅผ ์ถ๊ฐํ ํ ๊ทธ ๋ทฐ์ ๋ฐฐ๊ฒฝ์์ ๋ณด๋ผ์์ผ๋ก ์ค์ ํด ์ฃผ๊ธฐ.
9. ์ ๊ทผ๋ฐ, ์คํ ๋ฆฌ๋ณด๋์์ ์ฐ๋ฆฌ๊ฐ ์๋ฎฌ๋ ์ดํฐ์์ ์คํฌ๋กค ํ๋ฏ์ด ๋ณด๊ณ ์ถ์ ๋๊ฐ ์์ง?
โ ๊ทธ๋ผ ์ข์ฐ๋ก๋ ์ด๋ํ๊ฒ๋ ๋ง๋ค์ด ๋ณผ๊น?
2๏ธโฃ. Horizontal Scroll View
1. ์ฐ์ ์คํ ๋ทฐ์์ 3๊ฐ์ ๋ทฐ๋ฅผ ๋ฃ์๊ฑฐ์ผ.
์คํ๋ทฐ์ ๋์ด๊ฐ ํ์ฌ 600์ผ๋ก ์ค์ ๋์ด ์์ด -> ์ด๊ฑด ํค์ ํด๋ ๋ผ. ๊ทธ ์ด์ ๋ ์์ ๋ทฐ๋ค์ ๋์ด ๋ฐ๋ผ์ ์๋์ผ๋ก ์ค์ ์ด ๋ผ
2. ๋ฃ์ 3๊ฐ์ ๋ทฐ์ Heigth๋ฅผ ์๊ธฐ ์์ ์ผ๋ก ๋ ์ด์์์ ์ก์์ ๊ฐ๊ฐ 200์ผ๋ก ์ค์ ํด์ฃผ๊ธฐ
3. ์ด์ ๋ทฐ 3๊ฐ๋ฅผ ๋์์ ์ง์ฐ๊ณ ์คํ ๋ทฐ ์์ ์ปจํ ์ด๋ ๋ทฐ๋ฅผ ๋ฃ๋๋ค.
์ปจํ ์ด๋ ๋ทฐ 2๊ฐ๋ฅผ ์คํ ๋ทฐ ์์ ๋ฃ์ ํ ๊ฐ ์ปจํ ์ด๋ ๋ทฐ์ ๋์ด๋ฅผ ์ก์์ค๊ฑด๋ฐ 200์ผ๋ก ํ๋ค.
์ปจํ ์ด๋ ๋ทฐ๋ฅผ ๋ฃ์๋, ์ด๋ฏธ ์์ฑ๋ ์ปจํ ์ด๋ ๋ทฐ๋ฅผ ๋ณต์ฌ ๋ถ์ฌ๋ฃ๊ธฐ๋ฅผ ์ํํ๋ฉด, ํ๋์๊ณผ, ๋ ธ๋์์ผ๋ก ํํ๋ ๋ทฐ ์ปจํธ๋กค๋ฌ๊ฐ ์์ฑ๋์ง ์๋๋ฐ, ๊ทธ๋ด๋๋ ๋ทฐ ์ปจํธ๋กค๋ฌ๋ฅผ ํ๋ ๋ง๋ ํ์, ์ปจํ ์ด๋ ๋ทฐ ์ค ๋ทฐ ์ปจํ๋กค๋ฌ๋ฅผ ๊ฐ๊ณ ์์ง ์๋ ๊ฒ์ ์ฐ๊ฒฐํ๋ค.
์ด๋ ์ฐ๊ฒฐํ ๋๋ Embed ๋ฅผ ์ธ๊ทธ๋ก ์ฃผ๋ฉด ๋๋ค. -> ๋ทฐ ์ปจํธ๋กค๋ฌ ๋ชจ์์ด ์๋์ ๊ฐ์ด ์๊ฒ ๋ฐ๋๋ค.
4. ๋ค์์๋ ๋ ์ด๋ธ๊ณผ ์ปฌ๋ ์ ๋ทฐ๋ฅผ ๋ทฐ์ ๋ฃ๊ณ ์ปฌ๋ ์ ๋ทฐ ์์ ์ด๋ฏธ์ง ๋ทฐ๋ฅผ ์ถ๊ฐํ๋ค.
๋ ์ด์์์ ๋ ์ด๋ธ์ ํ(6), ํธ๋ ์ผ๋ง(8)
์ปฌ๋ ์ ๋ทฐ๋ ํธ๋ ์ผ๋ง(0), ๋ฆฌ๋ฉ(0), ๋ฐํ (6), ๋์ด(160)์ผ๋ก ์ค๋ค.
โ๏ธ ์ฌ๊ธฐ์ ๋ ธ๋์ ๋ฐฐ๊ฒฝ์ ๊ฐ์ง ์ปจํ ์ด๋๋ฅผ ๋ง๋ค๋ ์ค๋ฅ๊ฐ ๋ฐ์ํด์, ๊ทธ๋ฅ ํ๋์ ๋ณต๋ถํ ํ ์ฌ์ฉํ๋ค.
5. ๋ค์์ผ๋ก๋ ์ปค์คํ ํด๋์ค๋ฅผ ์ฐ๊ฒฐํ๊ณ , ์ปค์คํ ํด๋์ค์ IBOulet์ ํ์ดํ์ ์ฐ๊ฒฐํ๋ค.
๊ทธ๋ฆฌ๊ณ ์ปฌ๋ ์ ๋ทฐ๋ ๋ธ๋ฆฌ๊ฒ์ดํธ๋, ๋ฐ์ดํฐ์์ค ๋ทฐ ์ปจํธ๋กค๋ฌ ์์ํ๋๊ฑฐ ์์ง๋ง๊ธฐ.
๐ RecommendListViewController.swift ์ฝ๋!
//
// RecommendListViewController.swift
// MyNetflix
//
// Created by Hamlit Jason on 2021/06/29.
//
import UIKit
class RecommendListViewController: UIViewController {
@IBOutlet weak var sectionTitle: UILabel!
let viewModel = RecommentListViewModel()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateUI()
}
func updateUI() {
sectionTitle.text = viewModel.type.title
}
}
extension RecommendListViewController: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return viewModel.numOfItems
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RecommendCell", for: indexPath) as? RecommendCell else {
return UICollectionViewCell()
}
let movie = viewModel.item(at: indexPath.item)
cell.updateUI(movie: movie)
return cell
}
}
extension RecommendListViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 120, height: 160)
}
}
class RecommentListViewModel {
enum RecommendingType {
case award
case hot
case my
var title: String {
switch self {
case .award: return "์์นด๋ฐ๋ฏธ ํธํ ์ํฉ"
case .hot: return "์ทจํ์ ๊ฒฉ HOT ์ฝํ
์ธ "
case .my: return "๋ด๊ฐ ์ฐํ ์ฝํ
์ธ "
}
}
}
private (set) var type: RecommendingType = .my
private var items: [DummyItem] = []
var numOfItems: Int {
return items.count
}
func item(at index: Int) -> DummyItem {
return items[index]
}
func updateType(_ type: RecommendingType) {
self.type = type
}
func fetchItems() {
self.items = MovieFetcher.fetch(type)
}
}
class RecommendCell: UICollectionViewCell {
@IBOutlet weak var thumbnailImage: UIImageView!
func updateUI(movie: DummyItem) {
thumbnailImage.image = movie.thumbnail
}
}
class MovieFetcher {
static func fetch(_ type: RecommentListViewModel.RecommendingType) -> [DummyItem] {
switch type {
case .award:
let movies = (1..<10).map { DummyItem(thumbnail: UIImage(named: "img_movie_\($0)")!) }
return movies
case .hot:
let movies = (10..<19).map { DummyItem(thumbnail: UIImage(named: "img_movie_\($0)")!) }
return movies
case .my:
let movies = (1..<10).map { $0 * 2 }.map { DummyItem(thumbnail: UIImage(named: "img_movie_\($0)")!) }
return movies
}
}
}
struct DummyItem {
let thumbnail: UIImage
}
7. ๋ค์์ UpComingViewController.swift ๋ฅผ ๋ง๋ ํ์ ์๋์ ์ฝ๋์ ๊ฐ์ด ์์ฑํ๋ค.
import UIKit
class UpComingViewController : UIViewController {
var awardRecommendListViewController: RecommendListViewController!
var hotRecommendListViewController: RecommendListViewController!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "award" {
let destinationVC = segue.destination as? RecommendListViewController
awardRecommendListViewController = destinationVC
awardRecommendListViewController.viewModel.updateType(.award)
awardRecommendListViewController.viewModel.fetchItems()
} else if segue.identifier == "hot" {
let destinationVC = segue.destination as? RecommendListViewController
hotRecommendListViewController = destinationVC
hotRecommendListViewController.viewModel.updateType(.hot)
hotRecommendListViewController.viewModel.fetchItems()
}
}
}
8. ์ดํ์๋ ์ธ๊ทธ๋ฅผ ์ง์ ํด ์ค์ผ๊ฒ ์ง?
ํ๋์ ์ธ๊ทธ๋ award, ๋ ธ๋์ ์ธ๊ทธ๋ hot์ผ๋ก ์ธ๊ทธ๋ฅผ ์ค๋ค.
โ๏ธ์๋ฎฌ๋ ์ดํฐ๋ฅผ ๋๋ ธ์ ๋, ๋๋ ํ๋ฉด์ด ์ ๋๋ก ํ์๋์ง ์์๋๋ฐ, ์ฝ๋๋ฅผ ๋ค์ ์์ฑํ๋๋ ๋์๋ค.. ํน์๋ผ๋ ์๋๋ค๋ฉด, ๋ด ์ฝ๋๋ฅผ ๋ณต๋ถํด์ ์คํ ๋ฆฌ๋ณด๋ ์ชฝ์ ๋ฐ๊ฟ๋ณผ ๊ฒ!
์ด๋ฌ๋ฉด ์ผ๋จ ๋!!
์ดํ์๋ ํ์ด์ด๋ฒ ์ด์ค๋ฅผ ์ด์ฉํด์ ๊ฒ์์ด๋ฅผ ๋ฐ์์ค๋ ์์ ์ ํด๋ณด์!
(์ถ๊ฐ)
์คํฌ๋กค ๋ทฐ์์ RecommendListViewController ๊ฐ ์ด๋ป๊ฒ ๊ตฌ์ฑ๋์๋์ง ๊ถ๊ธํ๋ค๋ฉด...
์ฌ๊ธฐ์ RecommendListViewController๋ถ๋ถ์ ์ฐธ๊ณ ํ๊ธธ ๋ฐ๋
'โ ๏ธ deprecated โ ๏ธ > ํจ์บ (์ฌ์ธ์)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ธ ch 18 AVFoundation ์นดํ ๊ณ ๋ฆฌ ๋ณ๋ก ํ๊ตฌ (0) | 2021.07.05 |
---|---|
๐ฌ ch17 Netflix ํ์ฅ์ฑ ์ฝ๋๋ฆฌ๋ทฐ(firebase, kingfisher) + ch15 (0) | 2021.07.05 |
๐ผ ch15 ๊ฒ์์ ์ด์ฉํด ์๋ฒ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ ํ์ฑ๊น์ง! (0) | 2021.06.29 |
ch15 escaping๊ณผ non-escaping ํด๋ก์ ์ ๋ํด์ ์์๋ณด์ (0) | 2021.06.29 |
๐ ch15 ์ธ์คํด์ค ๋ฉ์๋ vs ํ์ ๋ฉ์๋ (0) | 2021.06.29 |