I am looking to have an interactive push view controller. So if the user pans from the right edge of the screen, it will pop to the next view controller. I have found this CocoaPods:
CodePudding user response:
You can do it programmatically with UIPageViewController:
Set your UIPageViewController class:
import UIKit
class MyControllerContainer: UIPageViewController {
// set UIPageViewController transition style
override init(transitionStyle style: UIPageViewController.TransitionStyle, navigationOrientation: UIPageViewController.NavigationOrientation, options: [UIPageViewController.OptionsKey : Any]? = nil) {
super.init(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
}
required init?(coder: NSCoder) {
super.init(coder: coder)
print("init(coder:) has not been implemented")
}
var pages = [UIViewController]()
var pageControl = UIPageControl()
let initialPage = 0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setup()
style()
layout()
}
}
Now set style, setup, and layout func:
extension MyControllerContainer {
func setup() {
dataSource = self
delegate = self
pageControl.addTarget(self, action: #selector(pageControlDragged(_:)), for: .valueChanged)
// create an array of viewController
let page1 = ViewController1()
let page2 = ViewController2()
let page3 = ViewController3()
pages.append(page1)
pages.append(page2)
pages.append(page3)
// set initial viewController to be displayed
setViewControllers([pages[initialPage]], direction: .forward, animated: true, completion: nil)
}
func style() {
pageControl.translatesAutoresizingMaskIntoConstraints = false
pageControl.currentPageIndicatorTintColor = .white
pageControl.pageIndicatorTintColor = UIColor(white: 1, alpha: 0.3)
pageControl.numberOfPages = pages.count
pageControl.currentPage = initialPage
}
func layout() {
view.addSubview(pageControl)
NSLayoutConstraint.activate([
pageControl.widthAnchor.constraint(equalTo: view.widthAnchor),
pageControl.heightAnchor.constraint(equalToConstant: 20),
view.bottomAnchor.constraint(equalToSystemSpacingBelow: pageControl.bottomAnchor, multiplier: 1),
])
}
}
set how we change controller when pageControl Dragged:
extension MyControllerContainer {
// How we change controller when pageControl Dragged.
@objc func pageControlDragged(_ sender: UIPageControl) {
setViewControllers([pages[sender.currentPage]], direction: .forward, animated: true, completion: nil)
}
}
after that set UIPageViewController delegate and datasource:
// MARK: - DataSources
extension MyControllerContainer: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
guard let currentIndex = pages.firstIndex(of: viewController) else { return nil }
if currentIndex == 0 {
return nil // stop presenting controllers when swipe from left to right in ViewController1
} else {
return pages[currentIndex - 1] // go previous
}
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let currentIndex = pages.firstIndex(of: viewController) else { return nil }
if currentIndex == 2 {
print("Last index...")
}
if currentIndex < pages.count - 1 {
return pages[currentIndex 1] // go next
} else {
return nil // stop presenting controllers when swipe from right to left in ViewController3
}
}
}
// MARK: - Delegates
extension MyControllerContainer: UIPageViewControllerDelegate {
// How we keep our pageControl in sync with viewControllers
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
guard let viewControllers = pageViewController.viewControllers else { return }
guard let currentIndex = pages.firstIndex(of: viewControllers[0]) else { return }
pageControl.currentPage = currentIndex
}
}
Now add your viewControllers, in my case 3:
// MARK: - ViewControllers
class ViewController1: UIViewController {
let mylabel1: UILabel = {
let label = UILabel()
label.text = "Controller 1"
label.textAlignment = .center
label.textColor = .white
label.font = .systemFont(ofSize: 20, weight: .semibold)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemRed
view.addSubview(mylabel1)
mylabel1.heightAnchor.constraint(equalToConstant: 50).isActive = true
mylabel1.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
mylabel1.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
mylabel1.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
}
class ViewController2: UIViewController {
let mylabel2: UILabel = {
let label = UILabel()
label.text = "Controller 2"
label.textAlignment = .center
label.textColor = .white
label.font = .systemFont(ofSize: 20, weight: .semibold)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemGreen
view.addSubview(mylabel2)
mylabel2.heightAnchor.constraint(equalToConstant: 50).isActive = true
mylabel2.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
mylabel2.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
mylabel2.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
}
class ViewController3: UIViewController {
let mylabel3: UILabel = {
let label = UILabel()
label.text = "Controller 3"
label.textAlignment = .center
label.textColor = .white
label.font = .systemFont(ofSize: 20, weight: .semibold)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .systemBlue
view.addSubview(mylabel3)
mylabel3.heightAnchor.constraint(equalToConstant: 50).isActive = true
mylabel3.widthAnchor.constraint(equalToConstant: view.frame.width).isActive = true
mylabel3.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
mylabel3.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}
}
This is the result: