In this article, we use SegmentedControl and PageViewController to change page.
Step 1: UI Design
Add Segmented Control in main page.
Add two ViewController and setup storyboard id : firstPage and secondPage.
Step 2: Reference SegmentedControl
Setup SegmentedControl object and click event in ViewController.swift.
Using UISegmentedControl.selectedSegmentIndex to get the current tab’s id.
Step 3: Setup PageViewController
Setup PageView Content
Add a PageViewController
1 var pageController: UIPageViewController !
Scroll view to change page.
1 pageController = UIPageViewController (transitionStyle: .Scroll , navigationOrientation:.Horizontal , options: nil )
Show the position of PageView.
1 pageController! .view.frame = CGRectMake (0 , mPageSegment.frame.origin.y + mPageSegment.frame.height, view.frame.size.width, view.frame.size.height);
Setup main page.
1 2 currentPageIndex = 0 ; pageController.setViewControllers([viewControllers.objectAtIndex(currentPageIndex) as! UIViewController ], direction: .Forward , animated: false ) {(isFinished:Bool ) -> Void in }
Monitoring the changed event of UIPageViewControllerDelegate and UIPageViewControllerDataSource.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 pageController.delegate = self ; pageController.dataSource = self ; extension ViewController : UIPageViewControllerDataSource { func pageViewController (pageViewController : UIPageViewController , viewControllerBeforeViewController viewController : UIViewController ) -> UIViewController ? { return nil } func pageViewController (pageViewController : UIPageViewController , viewControllerAfterViewController viewController : UIViewController ) -> UIViewController ? { return nil } } extension ViewController : UIPageViewControllerDelegate { func pageViewController (pageViewController : UIPageViewController , } }
Add the PageViewController.
1 2 self .addChildViewController(pageController)self .view.addSubview(pageController.view)
Step 4: Setup content when changing page
When scrolling page from left to right, if the previous page index smaller than 0, return nil.
1 2 3 4 5 6 7 8 9 func pageViewController (pageViewController : UIPageViewController , viewControllerBeforeViewController viewController : UIViewController ) -> UIViewController ? { currentPageIndex = viewController.view.tag let pageIndex = viewController.view.tag - 1 ; if pageIndex < 0 { return nil } return viewControllers[pageIndex] as? UIViewController }
When scrolling page from right to left, if the net page index larger than total page, return nil.
1 2 3 4 5 6 7 8 9 func pageViewController (pageViewController : UIPageViewController , viewControllerAfterViewController viewController : UIViewController ) -> UIViewController ? { currentPageIndex = viewController.view.tag let pageIndex = viewController.view.tag + 1 ; if pageIndex > 1 { return nil } return viewControllers[pageIndex] as? UIViewController }
Now we used Segmented Controll to control PageView.
Step 5: Change Segment
Using SegmentControll.selectedSegmentIndex to change selected tab.
In Step 4, add line : mPageSegment.selectedSegmentIndex = currentPageIndex.
Step 6: Click SegmentControll
When click SegmentControll many time, we will get the NSInternalInconsistencyException.
Because it have an animation when changing Pageview. If the animation isn’t finish, we click SegmentControll again, it throw an NSInternalInconsistencyException.
Solutions:
We using second method. Clicking SegmentedControll and setup the variable : enabled is false, when the animation finished, setup true.
Control SegmentedControll Goto previous page. direction: UIPageViewControllerNavigationDirection.Forward
Goto next page. direction: UIPageViewControllerNavigationDirection.Reverse
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @IBAction func tapSegment (sender : AnyObject ) { mPageSegment.enabled = false ; let index = (sender as! UISegmentedControl ).selectedSegmentIndex; if (currentPageIndex < index) { pageController! .setViewControllers([self .viewControllers[index] as! UIViewController ], direction: .Forward , animated: true , completion:{(isFinished: Bool ) in self .mPageSegment.enabled = true ; }) } else { pageController! .setViewControllers([self .viewControllers[index] as! UIViewController ], direction: .Reverse , animated: true , completion:{(isFinished: Bool ) in self .mPageSegment.enabled = true ; }) } currentPageIndex = index }
Using scroll method, when the animation is finished, set SegmentControll.enabled is true.
1 2 3 4 5 extension ViewController : UIPageViewControllerDelegate { func pageViewController (pageViewController : UIPageViewController , didFinishAnimating finished : Bool , previousViewControllers : [UIViewController ], transitionCompleted completed : Bool ) { mPageSegment.enabled = true ; } }
Source Code
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 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 import UIKitclass ViewController : UIViewController { @IBOutlet weak var mPageSegment: UISegmentedControl ! @IBAction func tapSegment (sender : AnyObject ) { mPageSegment.enabled = false ; let index = (sender as! UISegmentedControl ).selectedSegmentIndex; if (currentPageIndex < index) { pageController! .setViewControllers([self .viewControllers[index] as! UIViewController ], direction: .Forward , animated: true , completion:{(isFinished: Bool ) in self .mPageSegment.enabled = true ; }) } else { pageController! .setViewControllers([self .viewControllers[index] as! UIViewController ], direction: .Reverse , animated: true , completion:{(isFinished: Bool ) in self .mPageSegment.enabled = true ; }) } currentPageIndex = index } var pageController: UIPageViewController ! var viewControllers = NSMutableArray () var currentPageIndex : Int ! override func viewDidLoad () { super .viewDidLoad() let storyboard = UIStoryboard (name: "Main" , bundle: nil ) let firstViewController = storyboard.instantiateViewControllerWithIdentifier("firstPage" ) firstViewController.view.tag = 0 ; viewControllers.addObject(firstViewController) let secondViewController = storyboard.instantiateViewControllerWithIdentifier("secondPage" ) secondViewController.view.tag = 1 ; viewControllers.addObject(secondViewController) pageController = UIPageViewController (transitionStyle: .Scroll , navigationOrientation:.Horizontal , options: nil ) pageController! .view.frame = CGRectMake (0 , mPageSegment.frame.origin.y + mPageSegment.frame.height, view.frame.size.width, view.frame.size.height); currentPageIndex = 0 ; pageController.setViewControllers([viewControllers.objectAtIndex(currentPageIndex) as! UIViewController ], direction: .Forward , animated: false ) {(isFinished:Bool ) -> Void in } pageController.delegate = self ; pageController.dataSource = self ; self .addChildViewController(pageController) self .view.addSubview(pageController.view) } override func didReceiveMemoryWarning () { super .didReceiveMemoryWarning() } } extension ViewController : UIPageViewControllerDataSource { func pageViewController (pageViewController : UIPageViewController , viewControllerBeforeViewController viewController : UIViewController ) -> UIViewController ? { currentPageIndex = viewController.view.tag mPageSegment.selectedSegmentIndex = currentPageIndex; let pageIndex = viewController.view.tag - 1 ; if pageIndex < 0 { return nil } return viewControllers[pageIndex] as? UIViewController } func pageViewController (pageViewController : UIPageViewController , viewControllerAfterViewController viewController : UIViewController ) -> UIViewController ? { currentPageIndex = viewController.view.tag mPageSegment.selectedSegmentIndex = currentPageIndex; let pageIndex = viewController.view.tag + 1 ; if pageIndex > 1 { return nil } return viewControllers[pageIndex] as? UIViewController } } extension ViewController : UIPageViewControllerDelegate { func pageViewController (pageViewController : UIPageViewController , didFinishAnimating finished : Bool , previousViewControllers : [UIViewController ], transitionCompleted completed : Bool ) { mPageSegment.enabled = true ; } }
Result