Commit fac5e487 by Dmitry Stepanets

Working on scroll animation

parent e68fcfc6
......@@ -11,6 +11,8 @@ class OnboardingPageControl: UIView {
//Private
private let kSpacePerDot: CGFloat = 10
private let kDotSize: CGSize = .init(width: 9, height: 9)
private let kIndicatorSize: CGSize = .init(width: 6, height: 6)
private var currentPageIndex = 0
private let totalPagesCount: Int
private let indicator = CAShapeLayer()
private var dots = [CAShapeLayer]()
......@@ -18,50 +20,71 @@ class OnboardingPageControl: UIView {
init(totalPagesCount: Int) {
self.totalPagesCount = totalPagesCount
super.init(frame: .zero)
self.backgroundColor = .gray
prepareDots()
prepareIndicator()
}
override func layoutSubviews() {
super.layoutSubviews()
self.frame.size.width = CGFloat(totalPagesCount) * kDotSize.width + kSpacePerDot * (CGFloat(totalPagesCount) - 1)
self.frame.size.height = kDotSize.height
//Dots
for (index, dot) in dots.enumerated() {
let cgIndex = CGFloat(index)
let space = index == 0 ? 0 : kSpacePerDot
let rect = CGRect(origin: .init(x: cgIndex * (kDotSize.width + space), y: 0), size: kDotSize)
dot.path = CGPath(ellipseIn: rect, transform: nil)
print("Dot- index: \(index) rect: \(rect)")
}
//Update Y positions
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func scroll(toPage index: Int, progress: CGFloat) {
var scrollProgress = max(0, progress)
scrollProgress = min(progress, 1)
func scroll(toPage index: Int, screenTransitionProgress: CGFloat) {
guard screenTransitionProgress != 0 else { return }
var scrollProgress = max(0, screenTransitionProgress)
scrollProgress = min(screenTransitionProgress, 1)
print("[Page] scroll to \(index) progress: \(scrollProgress)")
let targetDot = dots[index]
let previousDot = dots[index == 0 ? 0 : index - 1]
//Scale
// let scaleDelta = (kDotSize.width - kIndicatorSize.width) * scrollProgress
// previousDot.frame.size = .init(width: kIndicatorSize.width + scaleDelta, height: kIndicatorSize.height + scaleDelta)
// print("[Frame] prev dot frame: \(previousDot.frame)")
let delta = targetDot.frame.origin.x - previousDot.frame.origin.x
indicator.frame.origin.x = previousDot.frame.origin.x + delta * scrollProgress
}
}
private extension OnboardingPageControl {
func prepareDots() {
for _ in 0..<totalPagesCount {
for index in 0..<totalPagesCount {
let dot = CAShapeLayer()
dot.fillColor = UIColor.blue.cgColor
let cgIndex = CGFloat(index)
let space = index == 0 ? 0 : kSpacePerDot
let size = index == 0 ? kIndicatorSize : kDotSize
let rect: CGRect
if index == 0 {
rect = .init(origin: .init(x: 0, y: (frame.height - kIndicatorSize.height) / 2), size: size)
}
else {
rect = .init(origin: .init(x: cgIndex * (size.width + space), y: 0), size: size)
}
dot.frame = rect
dot.backgroundColor = UIColor.blue.cgColor
dot.cornerRadius = kDotSize.height / 2
layer.addSublayer(dot)
dots.append(dot)
}
}
func prepareIndicator() {
indicator.fillColor = UIColor.red.cgColor
indicator.path = UIBezierPath(roundedRect: .init(origin: .zero, size: kDotSize),
cornerRadius: kDotSize.height / 2).cgPath
indicator.backgroundColor = UIColor.red.cgColor
indicator.frame = .init(origin: .zero, size: kDotSize)
indicator.cornerRadius = kIndicatorSize.height / 2
indicator.frame = .init(origin: .init(x: 0, y: (frame.height - kIndicatorSize.height) / 2),
size: kIndicatorSize)
layer.addSublayer(indicator)
}
}
......@@ -46,14 +46,16 @@ enum OnboardingControllerType {
}
}
class OnboardingPageController: UIPageViewController {
class OnboardingPageController: UIPageViewController, UIScrollViewDelegate {
private let coordinator: AppCoordinator
private let control = OnboardingPageControl(totalPagesCount: 3)
private let pageControl = UIPageControl()
private let closeButton = UIButton()
private var pages = [UIViewController]()
private let skipButton = SelfSizingButton()
private let nextButton = UIButton()
private let doneButton = UIButton()
private var currentPageIndex = 0
init(coordinator: AppCoordinator) {
self.coordinator = coordinator
......@@ -73,10 +75,13 @@ class OnboardingPageController: UIPageViewController {
super.viewDidLoad()
#if DEBUG
let control = OnboardingPageControl(totalPagesCount: 5)
view.addSubview(control)
control.frame.origin.x = 100
control.frame.origin.y = 80
view.addSubview(control)
control.snp.makeConstraints { make in
make.top.equalToSuperview().inset(80)
make.left.equalToSuperview().inset(100)
make.width.equalTo(47)
make.height.equalTo(9)
}
#else
fatalError("Remove in release")
#endif
......@@ -88,6 +93,7 @@ class OnboardingPageController: UIPageViewController {
prepareNextButton()
prepareDoneButton()
updateUI()
control.sizeToFit()
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
......@@ -112,12 +118,13 @@ class OnboardingPageController: UIPageViewController {
let currentViewController = viewControllers?.first,
let currentIndex = pages.firstIndex(of: currentViewController)
else {
return
return
}
let nextIndex = currentIndex + 1
guard nextIndex < pages.count else { return }
setViewControllers([pages[nextIndex]], direction: .forward, animated: true) {[weak self] _ in
self?.currentPageIndex = nextIndex
self?.pageControl.currentPage = nextIndex
self?.showDoneIfNeeded(for: nextIndex)
}
......@@ -162,6 +169,14 @@ private extension OnboardingPageController {
dataSource = self
delegate = self
setViewControllers([pages[0]], direction: .forward, animated: false)
//Try to find scroll view
for subview in view.subviews {
if subview.isKind(of: UIScrollView.self) {
let scrollView = subview as? UIScrollView
scrollView?.delegate = self
}
}
}
func preparePageControl() {
......@@ -249,6 +264,22 @@ private extension OnboardingPageController {
}
}
//MARK:- UIScrollView Delegate
extension OnboardingPageController {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageWidth = scrollView.contentSize.width / CGFloat(pages.count)
let progress = (scrollView.contentOffset.x - pageWidth) / pageWidth
print("progress: \(progress)")
let nextPageIndex = progress < 0 ? currentPageIndex - 1 : currentPageIndex + 1
if nextPageIndex > pages.count - 1 || nextPageIndex < 0 {
return
}
control.scroll(toPage: nextPageIndex, screenTransitionProgress: abs(progress))
}
}
//MARK:- UIPageViewController Data Source
extension OnboardingPageController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
......@@ -281,6 +312,7 @@ extension OnboardingPageController: UIPageViewControllerDelegate {
}
pageControl.currentPage = currentPageIndex
self.currentPageIndex = currentPageIndex
showDoneIfNeeded(for: currentPageIndex)
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment