우리가 보는 많은 앱들에는 CollectionView가 생각보다 핵심적인 기능으로 들어가는 경우가 많습니다.
Netfilx 앱에서 옆으로 밀어서 영화를 탐색할 때, coupang에서 찜한 목록 등을 볼 때 등
컬렉션 뷰는 테이블 뷰가 하는 일을 모두 할 수 있으면서도 레이아웃까지 가지고 있어서 수직 스크롤 뿐만 아니라 수평 스크롤도 가능합니다.
하지만 아래 앱처럼, 하나씩 넘기는 건 어떻게 구현할 수 있을까요??
하나씩 넘기고, 현재 내가 보고 있는 collectionView의 index가 어떤 인덱스인지까지 확인하는 방법은 무엇일까요?
일단 주우우우욱 스크롤이 되는 collectionView는 만들 수 있을 겁니다.
tableView를 만들 수 있다면, 분명히 쉽게 가능할 것입니다.
하지만 지금 내가 어떤 뷰를 보고 있고, 한장씩만 뷰가 넘어가게 하는 방법을 구현하기 위해서는
UIScrollViewDelegate에서 이 함수를 알아야 합니다.
먼저 tableView와 CollectionView 모두 scroll 기능을 가지고 있기 때문에, 당연히 UIScrollViewDelegate를 채택해서 scroll에 대한 기능을 우리 임의대로 구현해줄 수 있습니다.
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>)
이 함수는 무엇일까요??
함수 이름인 scrollViewWillEndDragging에서 알 수 있듯이
이 함수는 우리의 드래그가 끝나는 지점을 인식합니다.
즉 우리가 드래그를 하다가 손이 딱 떨어지는 지점을 인식하는거에요!!
그 떄, 이 함수가 실행이 됩니다!ㅎㅎㅎ
자! 그럼 이 함수를 어떻게 수정해주어야 할까요??
짜잔!! 갓 STACKOVERFLOW느님...ㅎㅎㅎㅎㅎㅎ
var currentIndex = 0
extension MainViewController: UIScrollViewDelegate {
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let layout = self.canvasCollectionView.collectionViewLayout as! UICollectionViewFlowLayout
let cellWidthIncludingSpacing = layout.itemSize.width + layout.minimumLineSpacing
var offset = targetContentOffset.pointee
let index = (offset.x + scrollView.contentInset.left) / cellWidthIncludingSpacing
var roundedIndex = round(index)
if scrollView.contentOffset.x > targetContentOffset.pointee.x {
roundedIndex = floor(index)
} else if scrollView.contentOffset.x < targetContentOffset.pointee.x {
roundedIndex = ceil(index)
} else {
roundedIndex = round(index)
}
if isOneStepPaging && (currentIndex != roundedIndex) {
let num: CGFloat = currentIndex > roundedIndex ? -1.0 : 1.0
// 부수적 처리들. taptic feedback 혹은 상단 날짜 변경 등
}
offset = CGPoint(x: roundedIndex * cellWidthIncludingSpacing - scrollView.contentInset.left, y: -scrollView.contentInset.top)
targetContentOffset.pointee = offset
}
}
자 쉽지는 않아보이지만, 하나씩 뜯어가다 보면 답을 찾을 수 있습니다.
아까 우리의 손가락이 드래그를 하다가 화면에서 떨어질 때, 이 함수가 발동된다고 했죠??
여기서는 index 를 정하는 부분만 잘 보면 됩니다!!
간단한 그림을 한번 그려볼게요!!
자 여기서 눈여겨 봐야 할 변수는 TargetContentOffset입니다!
이 함수 자체에서 가져오는 것으로, 손가락이 떨어지는 시점에 이 collectionViewCell의 x지점 있죠??
origin X라고 생각하면 편할거에요!!
그 지점이 전체 길이의 절반을 넘어갔는지 안넘어갔는지만 체크하는거에요!!!
자 절반을 넘어갔으면, 반올림 처리를 했을 때 값이 올라가겠죠??
그리고 이제 좀 더 아랫줄을 보면, currentIndex랑 비교를 하잖아요?
currentIndex는 우리가 처음에 보고 있는 collectionViewCell의 index 이에요!!
currentIndex랑 반올림 처리된 index 값과 비교해서 index 값이 더 크면 currentIndex를 1 올려주고
그 반대의 경우는 -1 을 해주고!!
같으면 그냥 그대로 두고!!
쉽죠??
그래서 결국 새로 계산된 인덱스 값으로 다시 offset을 정해주는 작업을 요 마지막 부분에서 해주게 됩니다!!
offset = CGPoint(x: roundedIndex * cellWidthIncludingSpacing - scrollView.contentInset.left, y: -scrollView.contentInset.top)
targetContentOffset.pointee = offset
'iOS 개발 > UIKit' 카테고리의 다른 글
[UIView] 정말 예쁜 blur Effect (0) | 2021.11.21 |
---|---|
[Swift] App 첫 로딩을 감지하는 법 (first loading detection) (0) | 2021.11.20 |
[Swift] 앱 안에서 메일 보내기 (0) | 2021.11.20 |
[GestureRecognizer] Gesture 잘 사용하기 - 동시에 여러 gesture 사용하기, 주의점 (0) | 2021.11.17 |
[UIImageView] image 색 변경하기 (0) | 2021.11.09 |
[UITableVIew] automaticDimension 이 되지 않을때 (0) | 2021.10.18 |
[UIView] view를 fade in, fade out 시키는 방법 (0) | 2021.09.21 |
[Animation] animation play 중간에 값 변경하는 몇가지 방법 (0) | 2021.09.21 |