forked from shadowfacts/Tusker
Don't use UIPageViewController for SegmentedPageViewController
This commit is contained in:
parent
baa9dfe0f1
commit
e4f3735c9f
|
@ -12,7 +12,7 @@ protocol SegmentedPageViewControllerPage: Hashable {
|
||||||
var segmentedControlTitle: String { get }
|
var segmentedControlTitle: String { get }
|
||||||
}
|
}
|
||||||
|
|
||||||
class SegmentedPageViewController<Page: SegmentedPageViewControllerPage>: UIPageViewController, UIPageViewControllerDelegate, TabbedPageViewController {
|
class SegmentedPageViewController<Page: SegmentedPageViewControllerPage>: UIViewController, UIPageViewControllerDelegate, TabbedPageViewController {
|
||||||
|
|
||||||
private(set) var pages: [Page]!
|
private(set) var pages: [Page]!
|
||||||
private let pageProvider: (Page) -> UIViewController
|
private let pageProvider: (Page) -> UIViewController
|
||||||
|
@ -23,9 +23,7 @@ class SegmentedPageViewController<Page: SegmentedPageViewControllerPage>: UIPage
|
||||||
var currentIndex: Int! {
|
var currentIndex: Int! {
|
||||||
pages.firstIndex(of: currentPage)
|
pages.firstIndex(of: currentPage)
|
||||||
}
|
}
|
||||||
var currentViewController: UIViewController! {
|
var currentViewController: UIViewController!
|
||||||
viewControllers?.first
|
|
||||||
}
|
|
||||||
|
|
||||||
let segmentedControl = ScrollingSegmentedControl<Page>()
|
let segmentedControl = ScrollingSegmentedControl<Page>()
|
||||||
|
|
||||||
|
@ -37,7 +35,7 @@ class SegmentedPageViewController<Page: SegmentedPageViewControllerPage>: UIPage
|
||||||
initialPage = pages.first!
|
initialPage = pages.first!
|
||||||
currentPage = pages.first!
|
currentPage = pages.first!
|
||||||
|
|
||||||
super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
|
super.init(nibName: nil, bundle: nil)
|
||||||
|
|
||||||
setPages(pages, animated: false)
|
setPages(pages, animated: false)
|
||||||
|
|
||||||
|
@ -104,12 +102,12 @@ class SegmentedPageViewController<Page: SegmentedPageViewControllerPage>: UIPage
|
||||||
initialPage = page
|
initialPage = page
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let direction: UIPageViewController.NavigationDirection
|
let direction: AnimationMode
|
||||||
if let prevIndex = currentIndex {
|
if let prevIndex = currentIndex {
|
||||||
let index = pages.firstIndex(of: page)!
|
let index = pages.firstIndex(of: page)!
|
||||||
direction = index - prevIndex > 0 ? .forward : .reverse
|
direction = index - prevIndex > 0 ? .forward : .reverse
|
||||||
} else {
|
} else {
|
||||||
direction = .forward
|
direction = .none
|
||||||
}
|
}
|
||||||
|
|
||||||
currentPage = page
|
currentPage = page
|
||||||
|
@ -121,12 +119,40 @@ class SegmentedPageViewController<Page: SegmentedPageViewControllerPage>: UIPage
|
||||||
pageControllers[page] = newController
|
pageControllers[page] = newController
|
||||||
}
|
}
|
||||||
|
|
||||||
setViewControllers([newController], direction: direction, animated: animated)
|
setViewController(newController, animated: animated ? direction : .none)
|
||||||
navigationItem.title = newController.title
|
navigationItem.title = newController.title
|
||||||
|
|
||||||
segmentedControl.setSelectedOption(page, animated: animated)
|
segmentedControl.setSelectedOption(page, animated: animated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func setViewController(_ newViewController: UIViewController, animated: AnimationMode) {
|
||||||
|
guard let currentViewController,
|
||||||
|
animated != .none else {
|
||||||
|
currentViewController?.removeViewAndController()
|
||||||
|
newViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
embedChild(newViewController)
|
||||||
|
self.currentViewController = newViewController
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard currentViewController !== newViewController else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.currentViewController = newViewController
|
||||||
|
newViewController.view.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
embedChild(newViewController)
|
||||||
|
let direction: CGFloat = animated == .forward ? 1 : -1
|
||||||
|
newViewController.view.transform = CGAffineTransform(translationX: direction * view.bounds.width, y: 0)
|
||||||
|
let animator = UIViewPropertyAnimator(duration: 0.5, timingParameters: UISpringTimingParameters(dampingRatio: 1, initialVelocity: .zero))
|
||||||
|
animator.addAnimations {
|
||||||
|
newViewController.view.transform = .identity
|
||||||
|
currentViewController.view.transform = CGAffineTransform(translationX: -1 * direction * self.view.bounds.width, y: 0)
|
||||||
|
}
|
||||||
|
animator.addCompletion { _ in
|
||||||
|
currentViewController.removeViewAndController()
|
||||||
|
}
|
||||||
|
animator.startAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: TabbedPageViewController
|
// MARK: TabbedPageViewController
|
||||||
|
|
||||||
func selectNextPage() {
|
func selectNextPage() {
|
||||||
|
@ -138,7 +164,14 @@ class SegmentedPageViewController<Page: SegmentedPageViewControllerPage>: UIPage
|
||||||
guard currentIndex > 0 else { return }
|
guard currentIndex > 0 else { return }
|
||||||
selectPage(pages[currentIndex - 1], animated: true)
|
selectPage(pages[currentIndex - 1], animated: true)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension SegmentedPageViewController {
|
||||||
|
enum AnimationMode: Equatable {
|
||||||
|
case none
|
||||||
|
case forward
|
||||||
|
case reverse
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SegmentedPageViewController: TabBarScrollableViewController {
|
extension SegmentedPageViewController: TabBarScrollableViewController {
|
||||||
|
|
Loading…
Reference in New Issue