Stacking Fire
손에 따라 애니메이션처럼 움직이는 커스텀 페이지 인디케이터(Page Indicator) 본문
회사 앱에 사용하기 위해 간단한 커스텀 인디케이터를 만들어 보았습니다.
결과물
환경
- iOS 9.0 +
- Swift 4.0
- SnapKit
개요
UIScrollViewdelegate의 scrollViewDidScroll(_:)을 이용하면, 스크롤되는 도중의 모든 contentOffset을 감시할 수 있습니다. 그 모든 타이밍에 페이지 인디케이터를 업데이트해주면, 나머지는 알아서 애니메이션처럼 보입니다. (이미 충분히 세부적인 contentOffset의 변화를 캐치할 수 있기 때문에, 애니메이션 함수는 필요가 없습니다.)
Code
scrollViewDidScroll(_:)
- 현재의 포지션을 전체 페이지 대비해서 계산합니다. 예를 들어 0.7라는 숫자는 0번 뷰에서 1번 뷰까지 70% 스크롤된 상태란 뜻입니다. (예제 코드는 이것과는 조금 다릅니다. 그 코드는 상단 스크롤 뷰가 무한스크롤이어서 contentOffset을 좀 특이하게 쓰고 있었기 때문입니다.)
var currentPosition = (scrollView.contentOffset.x / scrollView.frame.width)
그러면 이 포지션을 가지고 중간 단계를 표현해주기만 하면 자연스럽게 부드러운 애니메이션으로 보이게 될 겁니다. 해당 코드를 볼까요?
var currentPosition: Double = 0.0 {
didSet {
updateAppearance()
}
}
func updateAppearance() {
// 모든 애니메이션에서는 인접한 두 개의 점의 모양이 바뀝니다.
// currentPosition이 1.5라면 2번째 점과 3번째 점을 조정해야 하겠죠.
// 첫번째 점
let firstIndex = Int(currentProgress)
let firstDot = dots[firstIndex]
// 두번째 점
let secondIndex = (firstIndex + 1) % numberOfSteps
let secondDot = dots[secondIndex]
// 첫 번째 점으로부터 두 번째 점까지 사이에서 어느 정도 비율에 멈춰 있는가를 계산합니다.
let ratio = currentProgress - Double(firstIndex)
// 선택된 점의 width는 20.0이고 선택되지 않은 뷰의 width는 6.0입니다.
// 예를 들어 ratio가 0.3이라면, 첫번째 점의 가로 크기는 14.0 * 0.7 + 6.0가 됩니다.
firstDot.snp.updateConstraints { make in
make.width.equalTo((14.0 * (1.0 - ratio)) + 6.0)
}
// 위와 동일한 계산이지만, ratio가 다릅니다.
// 예를 들어 ratio가 0.3이라면, 두번째 점의 가로 크기는 14.0 * 0.3 + 6.0가 됩니다.
secondDot.snp.updateConstraints { make in
make.width.equalTo((14.0 * (ratio)) + 6.0)
}
// 오토 레이아웃으로 수정했기 때문에, 반영해 줍니다.
layoutIfNeeded()
}
예제
예제코드는 모양 뿐 아니라 색도 같이 바꿉니다. 그리고 위에서도 말씀드렸듯, 무한스크롤 덕분에 계산법이 조금 다릅니다.
'개발 > iOS' 카테고리의 다른 글
네비게이션 바 유지한 채 커스텀 푸시 / 팝 만들기 (2) | 2018.01.20 |
---|---|
UIKit, 안다고 생각했던 것들에 대하여 - 1 (0) | 2018.01.16 |
버전별 분기처리 #available (0) | 2018.01.10 |
오토 레이아웃과 함께 UIView의 애니메이션 기능 사용하기 (0) | 2018.01.10 |
이니시스의 이니페이 모바일 - iOS에서 주의할 점 (2) | 2017.12.27 |
Comments