일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- detect url
- Tuist
- base64 변환
- Side Menu
- scrolling tab
- url 관찰
- 기존 앱
- 개발자 면접
- ViewBuilder
- 스크롤 탭
- oberve url
- notifychanged
- List
- development language
- Android
- transformation.map
- swift #swift keychain #keychain 사용법
- swift
- GeometryReader
- pod install
- DevelopmentRegion
- Swift Package Manager
- DataBinding
- UIViewControllerTransitioningDelegate
- 상단 탭바
- ios
- SwiftUI
- url 추적
- convert base64
- UIPresentationController
- Today
- Total
버그 잡이
iOS/Swift 온보딩 화면 만들기 (with animation) 본문
요구 사항
1. 일반적인 온보딩 페이지
2. 넘길때 애니메이션 효과 적용 (이때 전환시 애니메이션 효과 적용)
(특히, 총 4개의 온보딩 page가 있는데 마지막 화면은 button의 모양이 변경됨)
사전 조사
온보딩 페이지를 만드는 방법은 크게 두 가지가 있습니다.
1. UIPageViewController 사용
2. UIScrollView 사용
UIPageViewController는 책장을 넘기는 형태의 뷰 생성을 도와주는 객체이고
UIScollview는 isPagingEnabled 속성을 true로 하면 scroll시 page를 넘기는 것과 같은 효과를 줄 수 있습니다.
결론적으로 UIScrollView를 활용하는 방식을 선택했습니다
두 가지 이유가 있는데
첫째는 pageControl를 맨 하단이 아닌 중간에 위치시키고 싶은데 UIPageViewController에서는 그것이 불가능해 보였습니다.
둘째는 UIScrollViewDelegate의 scrollViewdidScroll() 메서드를 사용해야했습니다.
didScroll() 메서드를 활용하면 스크롤 중 위치 값을 받을 수 있고 나는 그 값으로 애니메이션 효과를 줄 수 있다고 판단했습니다.
(UIPageViewController에도 값을 받을 수 있는 메서드들이 있지만 scrollViewdidScroll()처럼 scroll되는 모든 순간에 대해서 값을 받을 수 있는 메서드는 없는 것 같았습니다.)
구현 방법
1. scrollView 생성
isPagingEnabled = true로 설정해주고 indicator들을 없애줍니다.
저는 양끝에서 bounce 효과를 제거하기 위해서 속성을 false로 줬습니다.
private let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)).with {
$0.isPagingEnabled = true
$0.showsHorizontalScrollIndicator = false
$0.showsVerticalScrollIndicator = false
$0.bounces = false
}
2. page가 될 view들 추가
frame.origin.x = scrollWidth * CGFloat(index) 를 보고 scrollView와 그 안의 page들의 배치가 머리속에 그려지셨다면 성공입니다.
(스크린을 벗어나 page들이 옆으로 하나씩 붙는 모습을 머릿속으로 그리시면 됩니다)
private func setupPageView() {
var frame = CGRect(x: 0, y: 0, width: 0, height: 0)
frame.size = scrollView.frame.size
frame.size.height = scrollHeight
for index in 0..<pages.count {
frame.origin.x = scrollWidth * CGFloat(index)
let onboardingPage = OnBoardingPageView(frame: frame)
scrollView.addSubview(onboardingPage)
}
scrollView.contentSize = CGSize(width: scrollWidth * CGFloat(pages.count), height: scrollHeight)
}
3. 애니메이션 효과
원리는 간단합니다. scrollView.contentOffset / scrollView.frame.width 로 현재 페이지를 계산합니다.
여기서 point는 round()입니다. 반올림 처리로 인해서 페이와 페이지 중간 지점을 기준으로 넘어가면 올림 처리가 되고 넘어가지 않는다면 내림 처리가 됩니다.
이 pageNumber와 viewModel에 가지고 있는 currentPage 정보를 비교해서 변화가 있다면
changePageStyleWithAnimation()이라는 메서드를 실행시켜 애니메이션 효과를 주는 것입니다.
extension OnboardingViewController: UIScrollViewDelegate {
// 당연히 viewDidLoad에서 "scrollView.delegate = self" 도 해줘야겠죠?
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageNumber = Int(round(scrollView.contentOffset.x / scrollView.frame.size.width))
if viewModel.currentPage != pageNumber {
self.pageControl.currentPage = pageNumber
changePageStyleWithAnimation(prevPage: viewModel.currentPage, nextPage: pageNumber)
viewModel.currentPage = pageNumber
}
}
private func changePageStyleWithAnimation(prevPage: Int, nextPage: Int) {
UIView.transition(with: buttonContainerView, duration: 0.3, options: [.transitionCrossDissolve], animations: {
if nextPage == viewModel.lastPageIndex {
self.skipButton.isHidden = true
self.startButton.isHidden = false
self.scrollView.backgroundColor = .white
} else {
self.skipButton.isHidden = false
self.startButton.isHidden = true
self.scrollView.backgroundColor = .gray
}
})
}
}
chagePageStyleWithAnimation() 에서 button show/hidden 처리와 backgroundColor를 바꾸는 효과를 주었는데
여기에 추가적으로 view의 alpha값을 조정하여 view가 서서히 등장하는 효과 등을 줄 수 있습니다.
4. 버튼 클릭으로 화면 넘기기
아래와 같은 함수를 원하는 button에 addTarget으로 연결해주면 됩니다.
setContentOffset() 함수로 원하는 page로 이동할 수 있습니다.
button 클릭으로 scroll이 움직여도 scrollViewDidScroll()이 scrollView의 움직임을 인식하기 때문에 애니메이션 효과는 동일하게 적용됩니다.
@objc func nextButtonTapped() {
let pageNumber = pageControl.currentPage + 1
viewModel.currentPage = pageNumber
let x = CGFloat(pageNumber) * scrollView.frame.size.width
scrollView.setContentOffset(CGPoint(x:x, y:0), animated: true)
}
'IOS' 카테고리의 다른 글
iOS Universal Link 삽질 일기 (0) | 2021.05.12 |
---|---|
kin 라이브러리 - project.pbxproj 파일이 깨져 프로젝트가 열리지 않을때 (0) | 2021.04.16 |
tableView.reloadData() 이후 스크롤이 튀는 현상 해결방법 #automaticDimension #estimatedRowHeight (0) | 2020.12.07 |
XCode에서 SVG 파일 사용하기 #PDF vs SVG (0) | 2020.11.12 |
iOS - UIResponder, Responder Chain 알아보기 (0) | 2020.10.14 |