티스토리 뷰
collectionView에 간단히 paging을 설정할 수 있는 프로퍼티가 있다.
collectionView.isPagingEnabled = true
위 코드와 같이 간단히 가능하다.
하지만 이 코드로는 상하좌우에 여백이 생기면 스크롤 시 어그러지는 현상이 발생된다.
난 아래와 같은 페이징 효과를 원했다!!!
그래서 검색을 통해 코드를 보고 내가 원하는대로 만들어 보았다.
아래는 collectionView에 대한 초기 설정이다.
class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
let itemColors = [UIColor.red, UIColor.yellow, UIColor.blue, UIColor.green]
override func viewDidLoad() {
super.viewDidLoad()
// width, height 설정
let cellWidth = view.frame.width - 100
let cellHeight = view.frame.height - 100
// 상하, 좌우 inset value 설정
let insetX = (collectionView.bounds.width - cellWidth) / 2.0
let insetY = (collectionView.bounds.height - cellHeight) / 2.0
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: cellWidth, height: cellHeight)
layout.minimumLineSpacing = 15
layout.scrollDirection = .horizontal
collectionView.contentInset = UIEdgeInsets(top: insetY, left: insetX, bottom: insetY, right: insetX)
collectionView.delegate = self
collectionView.dataSource = self
// 스크롤 시 빠르게 감속 되도록 설정
collectionView.decelerationRate = UIScrollViewDecelerationRateFast
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
scrollViewWillEndDragging 은 사용자가 스크롤을 하고 스크린과 손이 떨어졌을 때 호출되는 메서드이다.
이를 통해 스크롤 할 때, content의 위치를 조정하여 페이징되는 효과를 낼 수 있었다.
우선 메서드의 파라미터가 무엇을 나타내는지는 아래 공식 홈페이지에 잘 나와 있었다.
scrollViewwillEndDragging(_:withVelocity:targetContentOffset:) - 공식 홈페이지
간단히 적어보면
scrollView - 터치를 종료한 스크롤 뷰
velocity - 스크롤하다 터치 해제시 속도
targetContentOffset - 스크롤 속도가 줄어들어 정지될 때 예상되는 위치
아래 코드와 설명을 나름... 정리해 보았다...
extension ViewController : UIScrollViewDelegate
{
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer)
{
// item의 사이즈와 item 간의 간격 사이즈를 구해서 하나의 item 크기로 설정.
let layout = self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
let cellWidthIncludingSpacing = layout.itemSize.width + layout.minimumLineSpacing
// targetContentOff을 이용하여 x좌표가 얼마나 이동했는지 확인
// 이동한 x좌표 값과 item의 크기를 비교하여 몇 페이징이 될 것인지 값 설정
var offset = targetContentOffset.pointee
let index = (offset.x + scrollView.contentInset.left) / cellWidthIncludingSpacing
var roundedIndex = round(index)
// scrollView, targetContentOffset의 좌표 값으로 스크롤 방향을 알 수 있다.
// index를 반올림하여 사용하면 item의 절반 사이즈만큼 스크롤을 해야 페이징이 된다.
// 스크로로 방향을 체크하여 올림,내림을 사용하면 좀 더 자연스러운 페이징 효과를 낼 수 있다.
if scrollView.contentOffset.x > targetContentOffset.pointee.x {
roundedIndex = floor(index)
} else {
roundedIndex = ceil(index)
}
// 위 코드를 통해 페이징 될 좌표값을 targetContentOffset에 대입하면 된다.
offset = CGPoint(x: roundedIndex * cellWidthIncludingSpacing - scrollView.contentInset.left, y: -scrollView.contentInset.top)
targetContentOffset.pointee = offset
}
}
설명과 정리를 잘 하지 못하여 간단하게 예제를 만들어 보았다.
하단에 예제와 가장 도움을 많이 받은 영상을 첨부 해 놓았다.
CollectionViewPagingExample - Github
UICollectionView with Swift: Build Carousel Like Home Screen - YouTube
정리하며 알게된 사실... "swift collectionView paging" 으로 많이 검색했는데 "swift carousel effect"라고 검색하면 더 잘 나오는 것 같다....
페이징 할 때 하나씩만 넘어가도록 하는 코드 업데이트 했습니다.
아래는 기존 scrollViewWillEndDragging 메소드에서 수정될 부분만을 보여주기 위한 코드입니다.
extension ViewController : UIScrollViewDelegate
{
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer)
{
...
if scrollView.contentOffset.x > targetContentOffset.pointee.x {
roundedIndex = floor(index)
} else {
roundedIndex = ceil(index)
}
...
}
}
이제 위 코드 부분을 아래와 같이 수정해 보았습니다.
var currentIndex: CGFloat = 0 // 현재 보여지고 있는 페이지의 인덱스
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer)
{
...
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 currentIndex > roundedIndex {
currentIndex -= 1
roundedIndex = currentIndex
} else if currentIndex < roundedIndex {
currentIndex += 1
roundedIndex = currentIndex
}
...
}
기존에는 스크롤한 값에 대해 페이징되는 인덱스 값을 구하여, 인덱스 크기만큼 페이징 처리를 했습니다.
업데이트 된 코드에서는 페이징되는 인덱스 크기를 1로 수정하여 하나씩만 페이징 되도록 처리했습니다.
수정된 코드는 깃허브에 업데이트 되어 있습니다!! 🤫🤫🤫
'Swift' 카테고리의 다른 글
내장된 notificationName 사용하여 notification 등록해보기 (0) | 2018.08.21 |
---|---|
urlencoded 방식으로 POST 요청 보내기 (1) | 2018.08.20 |
url에 한글이 있을 경우 간단히 인코딩하는 방법 (1) | 2018.07.11 |
statusBar 삽질기! (0) | 2018.07.10 |
collectionviewcell의 reuse에 관한 삽질!! (0) | 2018.07.07 |
- Total
- Today
- Yesterday
- AssociatedObject
- UIButton
- carousel
- ssh
- Cleancode
- AVFoundation
- Realm
- AVKit
- Design Pattern
- IOS
- TDD
- BaseViewController
- customAlertView
- NIB
- RECORDING
- xib
- HLS
- Coordinator
- testing
- pagingView
- permission error
- http live streaming
- UIBarButtonItem
- CollectionView
- m3u8
- Swift
- Video
- UIControl
- Closure
- database
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |