Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- uitableview
- uiscrollview
- collectionview
- Clean Code
- rxswift
- tableView
- SWIFT
- HIG
- swiftUI
- ios
- map
- clean architecture
- Protocol
- 스위프트
- combine
- 클린 코드
- 애니메이션
- swift documentation
- RxCocoa
- Human interface guide
- UICollectionView
- ribs
- Refactoring
- 리펙터링
- 리팩토링
- MVVM
- 리펙토링
- Xcode
- Observable
- UITextView
Archives
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[iOS - swift] 1. 스크롤 영역을 암시해주는 Carousel 구현 방법 (UICollectionView, 수평 스크롤 뷰, paging 구현) 본문
UI 컴포넌트 (swift)
[iOS - swift] 1. 스크롤 영역을 암시해주는 Carousel 구현 방법 (UICollectionView, 수평 스크롤 뷰, paging 구현)
jake-kim 2022. 6. 26. 14:461. 스크롤 영역을 암시해주는 Carousel 구현 - (UICollectionView, 수평 스크롤 뷰, paging 구현)
2. 스크롤 영역을 암시해주는 Carousel 구현 - 포커스 영역 이펙트
구현 아이디어
- 수평 스크롤 뷰 구현 방법은 FlowLayout+UICollectionView으로 구현하는 방법인 이전 포스팅 글 참고
- 양옆에 item이 보여서, 스크롤 할 수 있다는 암시를 주도록 paging이 되어야 하므로 이 것을 구현하는 것이 핵심
- paging을 직접 구현 `isPagingEnabled = false`
- 스크롤이 페이징처럼 보여지기 `decelearationRate = .fast`
- 페이징을 scrollViewWillEndDragging에서 구현 (UICollectionViewDelegateFlowLayout의 델리게이트 메소드)
- 페이징 구현 방법
- scrollViewWillEndDragging 메소드에서 현재까지 스크롤된 크기를 구할 수 있고, 이 스크롤 크기를 다시 수정할 수 있으므로 이곳에서 구현
- 스크롤된 크기를 구하고, item의 index값을 구함
- index값을 구하면, 아래 식으로 다시 페이징되게하여 원하는 곳으로 스크롤 되도록 입력이 가능
- 스크롤 위치 = (index * cellWidth) - insetX
구현
- UICollectionView의 cell 정의
final class MyCollectionViewCell: UICollectionViewCell {
static let id = "MyCollectionViewCell"
// MARK: UI
private let myView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
// MARK: Initializer
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override init(frame: CGRect) {
super.init(frame: frame)
self.contentView.addSubview(self.myView)
NSLayoutConstraint.activate([
self.myView.leftAnchor.constraint(equalTo: self.contentView.leftAnchor),
self.myView.rightAnchor.constraint(equalTo: self.contentView.rightAnchor),
self.myView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor),
self.myView.topAnchor.constraint(equalTo: self.contentView.topAnchor),
])
}
override func prepareForReuse() {
super.prepareForReuse()
self.prepare(color: nil)
}
func prepare(color: UIColor?) {
self.myView.backgroundColor = color
}
}
private var randomColor: UIColor {
UIColor(red: CGFloat(drand48()), green: CGFloat(drand48()), blue: CGFloat(drand48()), alpha: 1.0)
}
- 예제로 사용할 데이터인, randomColor 정의
private var randomColor: UIColor {
UIColor(red: CGFloat(drand48()), green: CGFloat(drand48()), blue: CGFloat(drand48()), alpha: 1.0)
}
- ViewController 선언
import UIKit
class ViewController: UIViewController {
}
- itemSize, itemSpacing, insetX 정의
// in ViewController
private enum Const {
static let itemSize = CGSize(width: 300, height: 400)
static let itemSpacing = 24.0
static var insetX: CGFloat {
(UIScreen.main.bounds.width - Self.itemSize.width) / 2.0
}
static var collectionViewContentInset: UIEdgeInsets {
UIEdgeInsets(top: 0, left: Self.insetX, bottom: 0, right: Self.insetX)
}
}
- flowLayout과 collectionView 선언
- flowLayout에서 itemSize와 spacing을 정의
- collectionView에서 isPagingEnabled = false로,decelerationRate를 fast로 설정
// in ViewController
private let collectionViewFlowLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.itemSize = Const.itemSize // <-
layout.minimumLineSpacing = Const.itemSpacing // <-
layout.minimumInteritemSpacing = 0
return layout
}()
private lazy var collectionView: UICollectionView = {
let view = UICollectionView(frame: .zero, collectionViewLayout: self.collectionViewFlowLayout)
view.isScrollEnabled = true
view.showsHorizontalScrollIndicator = false
view.showsVerticalScrollIndicator = true
view.backgroundColor = .clear
view.clipsToBounds = true
view.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.id)
view.isPagingEnabled = false // <- 한 페이지의 넓이를 조절 할 수 없기 때문에 scrollViewWillEndDragging을 사용하여 구현
view.contentInsetAdjustmentBehavior = .never // <- 내부적으로 safe area에 의해 가려지는 것을 방지하기 위해서 자동으로 inset조정해 주는 것을 비활성화
view.contentInset = Const.collectionViewContentInset // <-
view.decelerationRate = .fast // <- 스크롤이 빠르게 되도록 (페이징 애니메이션같이 보이게하기 위함)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
- 데이터소스와 레이아웃 정의
// in ViewController
private var items = (0...100).map { _ in randomColor }
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(self.collectionView)
NSLayoutConstraint.activate([
self.collectionView.leftAnchor.constraint(equalTo: self.view.leftAnchor),
self.collectionView.rightAnchor.constraint(equalTo: self.view.rightAnchor),
self.collectionView.heightAnchor.constraint(equalToConstant: Const.itemSize.height),
self.collectionView.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
])
self.collectionView.dataSource = self
self.collectionView.delegate = self
}
- 페이징을 구현하는 부분 `scrollViewWillEndDragging`
- 스크롤된 크기를 구하고, item의 index값을 구함
- index값을 구하면, 아래 식으로 다시 페이징되게하여 원하는 곳으로 스크롤 되도록 입력이 가능
- 스크롤 위치 = (index * cellWidth) - insetX
extension ViewController: UICollectionViewDelegateFlowLayout {
func scrollViewWillEndDragging(
_ scrollView: UIScrollView,
withVelocity velocity: CGPoint,
targetContentOffset: UnsafeMutablePointer<CGPoint>
) {
let scrolledOffsetX = targetContentOffset.pointee.x + scrollView.contentInset.left
let cellWidth = Const.itemSize.width + Const.itemSpacing
let index = round(scrolledOffsetX / cellWidth)
targetContentOffset.pointee = CGPoint(x: index * cellWidth - scrollView.contentInset.left, y: scrollView.contentInset.top)
}
}
* 전체 코드: https://github.com/JK0369/ExCarousel
'UI 컴포넌트 (swift)' 카테고리의 다른 글
[iOS - swift] 인스타그램 썸네일 프로필 UI 구현 방법 (0) | 2022.06.28 |
---|---|
[iOS - swift] 2. 스크롤 영역을 암시해주는 Carousel 구현 - 포커스 영역 이펙트 (7) | 2022.06.27 |
[iOS - swift] 수평 스크롤 뷰와 커스텀 Indicator View (쿠팡 수평 스크롤 뷰, 스크롤 IndicatorView) (0) | 2022.06.09 |
[iOS - swift] Custom Slider (커스텀 슬라이더), point, beginTracking, continueTracking, endTracking (0) | 2022.06.03 |
[iOS - swift] Custom Switch (커스텀 스위치) 구현 방법, touchesEnded (0) | 2022.06.02 |
Comments