Reputation: 2451
Searched a lot for this one, but couldn't find a proper solution yet.
Is it possible to disable the bounce effect of a UIPageViewController
and still use the UIPageViewControllerTransitionStyleScroll
?
Upvotes: 58
Views: 35600
Reputation: 3225
To disable bounces on an UIPageViewController, you can do this (in Swift 5), assuming you declared myPages var as a array of UIViewController :
// Add Scroll delegate
class myController: UIPageViewController, UIScrollViewDelegate { ... }
// Declare currentIdx & scrollview vars
private var currentIdx: Int = 0
private var scrollview: UIScrollView?
// In ViewDidLoad, add delegate & stock scrollview
for view in view.subviews {
if let subView = view as? UIScrollView {
subView.delegate = self
scrollview = subView
}
}
// Retrieve current index like this somewhere in your code
guard let currentViewController = viewControllers?.first, let currentIndex = myPages.firstIndex(of: currentViewController) else {
return
}
currentIdx = index
// Declare private func to calculate bounces if needed
private func setBounces() {
let max = myPages.count - 1
scrollview?.bounces = currentIdx > 0 && currentIdx < max
}
// Add UIScrollViewDelegate methods
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
setBounces()
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
setBounces()
}
Upvotes: 0
Reputation: 1272
find the UIScrollView
instance from UIPageViewController
subviews,
and simply set bounces
property to false
and you are good to go.
let vc = UIPageViewController(transitionStyle: UIPageViewController.TransitionStyle.scroll, navigationOrientation: UIPageViewController.NavigationOrientation.horizontal, options: [:])
for subview in vc.view.subviews {
if let scrollView = subview as? UIScrollView {
scrollView.bounces = false
break
}
}
Upvotes: -2
Reputation: 10096
One should implement UIScrollViewDelegate
methods to restrict edge scrolls
class MyPageViewController: UIPageViewController {
override func loadView() {
super.loadView()
view.subviews.forEach { sv in
if let scrollView = sv as? UIScrollView {
scrollView.delegate = self
}
}
}
}
extension MyPageViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if currentPage == 0, scrollView.contentOffset.x + scrollView.contentInset.left < 0 {
scrollView.contentOffset = CGPoint(x: -scrollView.contentInset.left, y: scrollView.contentOffset.y)
}
else if currentPage == pageCount - 1, scrollView.contentInset.right < 0, scrollView.contentOffset.x + scrollView.contentInset.right > 0 {
scrollView.contentOffset = CGPoint(x: -scrollView.contentInset.right, y: scrollView.contentOffset.y)
}
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if currentPage == 0, scrollView.contentOffset.x + scrollView.contentInset.left < 0 {
targetContentOffset.pointee = CGPoint(x: -scrollView.contentInset.left, y: targetContentOffset.pointee.y)
}
else if currentPage == pageCount - 1, scrollView.contentInset.right < 0, scrollView.contentOffset.x + scrollView.contentInset.right > 0 {
targetContentOffset.pointee = CGPoint(x: -scrollView.contentInset.right, y: targetContentOffset.pointee.y)
}
}
}
Here currentPage
is the current page index, pageCount
is the total page count.
Upvotes: 0
Reputation: 8303
Edit: Do not use this solution. Left here for reference and educational purposes I learned afterwards that this introduces a bug where about 5% of the time, the user can't page in the same direction. They have to page back, then forward again to continue.
If you're using a UIPageViewControllerDataSource
, a relatively simple workaround (and a bit hacky) is to disable bouncing each time the pageViewController:viewControllerBeforeViewController:
delegate method is called. Here is an example implementation:
@interface YourDataSourceObject ()
@property (strong, nonatomic) UIScrollView *scrollView;
@end
@implementation
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController {
if (!self.scrollView) {
for (UIView *view in pageViewController.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
self.scrollView = (UIScrollView *)view;
}
}
}
self.scrollView.bounces = NO;
// Your other logic to return the correct view controller.
}
@end
Upvotes: -2
Reputation: 4065
This did the trick for me in viewDidLoad
:
for subview in pager.view.subviews {
if let scrollView = subview as? UIScrollView {
scrollView.bounces = false
scrollView.alwaysBounceHorizontal = false
break
}
}
Upvotes: -2
Reputation: 368
In case you wish to disable scrollview on a UIPageViewController
subclass entirely, you can use the snippet below. Note that this disables not only the bouncing but the horizontal scrolling of the pages as well.
In my case I had a UISegmentedControl to switch between the pages in the PageViewController so disabling scrolling vertically was completely fine and working for me. Hope it helps someone else too.
class MyPageViewController: UIPageViewController {
private lazy var scrollView: UIScrollView = { view.subviews.compactMap({ $0 as? UIScrollView }).first! }()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.isScrollEnabled = false
}
}
Upvotes: 1
Reputation: 563
If you keep track of your currentIndex then the below should be sufficient but its a little buggy because there is a random scenario where it stops scrolling altogether.
I think the scrollView.bounces is a little buggy, perhaps I am missing something because most of the time it works fine, if anyone is able to have a solution based on the below it would be great please.
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
scrollView.bounces = currentIndex == 0 ||
currentIndex == controllers.count - 1
? false
: true
}
Upvotes: 4
Reputation: 8607
Below is a complete solution that, unlike with other answers, doesn't require you to write/test your own code for tracking the index of the currently displayed page.
Assuming that your pages are stored in sourcePageViewControllers
immutable array and after you've created your UIPageViewController
as myPageViewController
:
let scrollView = myPageViewController.view.subviews.compactMap({ $0 as? UIScrollView }).first!
scrollView.delegate = <instance of YourScrollViewDelegateClass>
And then:
extension YourScrollViewDelegateClass: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
guard sourcePageViewControllers.count > 1 else {
scrollView.isScrollEnabled = false
return
}
guard let viewControllers = myPageViewController.viewControllers, viewControllers.count != 0 else { return }
let baseRecord =
viewControllers
.map { [superview = myPageViewController.view!] viewController -> (viewController: UIViewController, originX: CGFloat) in
let originX = superview.convert(viewController.view.bounds.origin, from: viewController.view).x
return (viewController: viewController, originX: originX)
}
.sorted(by: { $0.originX < $1.originX })
.first!
guard let baseIndex = sourcePageViewControllers.firstIndex(of: baseRecord.viewController) else { return }
let baseViewControllerOffsetXRatio = -baseRecord.originX/scrollView.bounds.width
let progress = (CGFloat(baseIndex) + baseViewControllerOffsetXRatio)/CGFloat(sourcePageViewControllers.count - 1)
if !(0...1 ~= progress) {
scrollView.isScrollEnabled = false
scrollView.isScrollEnabled = true
}
}
}
Upvotes: 5
Reputation: 334
My solution in Swift 5
In my scenario, I first load the UIPageViewController
on the second page. And I have a total of three pages so I open on the middle one.
Here's the code of my UIPageViewController
import UIKit
class MainPageViewController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate, UIScrollViewDelegate {
let idList = ["OverviewController", "ImportantItemsController", "ListMenuController"] // A list of all of my viewControllers' storyboard id
var currentPage = 1 // Tracking the current page
override func viewDidLoad() {
super.viewDidLoad()
setupPageController()
for subview in self.view.subviews { // Getting the scrollView
if let scrollView = subview as? UIScrollView {
scrollView.delegate = self
break;
}
}
}
// UIPageViewControllerDataSource
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let index = idList.firstIndex(of: viewController.restorationIdentifier!)!
if (index > 0) {
return storyboard?.instantiateViewController(withIdentifier: idList[index - 1])
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let index = idList.firstIndex(of: viewController.restorationIdentifier!)!
if (index < idList.count - 1) {
return storyboard?.instantiateViewController(withIdentifier: idList[index + 1])
}
return nil
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return idList.count
}
// UIPageViewControllerDelegate
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
guard let vc = pageViewController.viewControllers?.first else { return }
switch vc {
case is ImportantItemsController:
currentPage = 1
case is OverviewController:
currentPage = 0
default:
currentPage = 2
}
}
}
// ScrollViewDelegate
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let totalViewControllersInPageController = idList.count
if (currentPage == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width) {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0);
} else if (currentPage == totalViewControllersInPageController - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width) {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0);
}
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let totalViewControllersInPageController = idList.count
if (currentPage == 0 && scrollView.contentOffset.x <= scrollView.bounds.size.width) {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0);
} else if (currentPage == totalViewControllersInPageController - 1 && scrollView.contentOffset.x >= scrollView.bounds.size.width) {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0);
}
}
fileprivate func setupPageController() {
let controller = storyboard?.instantiateViewController(withIdentifier: idList[1]) as! ImportantItemsController // Loading on the second viewController
setViewControllers([controller], direction: .forward, animated: true, completion: nil)
dataSource = self
delegate = self
}
}
Upvotes: 1
Reputation: 4984
Edited answer of Dong Ma, where:
currentIndex
when swipes very quickInfo:
How to:
UIViewController
where UIPageViewController
is added as child VC.class ViewController: UIViewController {
var pageNavigationController: UIPageViewController!
private var lastPosition: CGFloat
private var nextIndex: Int
var currentIndex: Int
// rest of UI's setups
}
ViewController
as delegate of UIPageViewController
:extension ViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
guard
let currentVisibleViewController = pageViewController.viewControllers?.first,
let nextIndex = pageViewControllers.firstIndex(of: currentVisibleViewController)
else {
return
}
self.nextIndex = nextIndex
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed, let currentVisibleViewController = pageViewController.viewControllers?.first, let newIndex = pageViewControllers.firstIndex(of: currentVisibleViewController) {
self.currentIndex = newIndex
}
self.nextIndex = self.currentIndex
}
}
ViewController
as datasource of UIPageController
:extension ViewController: UIPageViewControllerDataSource {
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
// provide next VC
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
// provide prev VC
}
// IMPORTANT: that's the key why it works, don't forget to add it
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return currentIndex
}
}
ViewController
as delegate of UIPageViewController
's UIScrollView
:// MARK: - UIScrollViewDelegate (disable bouncing for UIPageViewController)
extension BasePaginationVC: UIScrollViewDelegate {
func attachScrollViewDelegate() {
for subview in pageNavigationController.view.subviews {
if let scrollView = subview as? UIScrollView {
scrollView.delegate = self
lastPosition = scrollView.contentOffset.x
break
}
}
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
switch UIView.userInterfaceLayoutDirection(for: view.semanticContentAttribute) {
case .leftToRight:
if nextIndex > currentIndex {
if scrollView.contentOffset.x < (lastPosition - (0.9 * scrollView.bounds.size.width)) {
currentIndex = nextIndex
}
} else {
if scrollView.contentOffset.x > (lastPosition + (0.9 * scrollView.bounds.size.width)) {
currentIndex = nextIndex
}
}
if currentIndex == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
} else if currentIndex == pageViewControllers.count - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
case .rightToLeft:
if nextIndex > currentIndex {
if scrollView.contentOffset.x > (lastPosition + (0.9 * scrollView.bounds.size.width)) {
currentIndex = nextIndex
}
} else {
if scrollView.contentOffset.x < (lastPosition - (0.9 * scrollView.bounds.size.width)) {
currentIndex = nextIndex
}
}
if currentIndex == pageViewControllers.count - 1 && scrollView.contentOffset.x < scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
} else if currentIndex == 0 && scrollView.contentOffset.x > scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
@unknown default:
fatalError("unknown default")
}
lastPosition = scrollView.contentOffset.x
}
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
switch UIView.userInterfaceLayoutDirection(for: view.semanticContentAttribute) {
case .leftToRight:
if currentIndex == 0 && scrollView.contentOffset.x <= scrollView.bounds.size.width {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0)
} else if currentIndex == pageViewControllers.count - 1 && scrollView.contentOffset.x >= scrollView.bounds.size.width {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
case .rightToLeft:
if currentIndex == pageViewControllers.count - 1 && scrollView.contentOffset.x <= scrollView.bounds.size.width {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0)
} else if currentIndex == 0 && scrollView.contentOffset.x >= scrollView.bounds.size.width {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
@unknown default:
fatalError("unknown default")
}
}
}
Upvotes: 1
Reputation: 1330
@Dong Ma's approach is perfect but it can be a little bit improved and simplified.
Code to put into viewDidLoad:
for subview in view.subviews {
if let scrollView = subview as? UIScrollView {
scrollView.delegate = self
break
}
}
Implementation for scrollViewDidScroll:
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (currentPage == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width) || (currentPage == totalNumberOfPages - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width) {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
}
Implementation for scrollViewWillEndDragging:
public func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if (currentPage == 0 && scrollView.contentOffset.x <= scrollView.bounds.size.width) || (currentPage == totalNumberOfPages - 1 && scrollView.contentOffset.x >= scrollView.bounds.size.width) {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
}
Upvotes: 1
Reputation: 83
Another option is to set ScrollView.bounce = false. It solved my problem with pageViewController's(Of course not about ScrollView) scrolling bounce. Bounce is disabled, and all page can scroll without bounces.
Upvotes: 1
Reputation: 1073
Add the <UIScrollViewDelegate>
delegate to your UIPageViewController's header
Set the UIPageViewController's underlying UIScrollView's delegates to their parent in viewDidLoad
:
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
((UIScrollView *)view).delegate = self;
break;
}
}
The implementation for scrollViewDidScroll is to reset the contentOffset to the origin (NOT (0,0), but (bound.size.width, 0)) when the user is reaching out of the bounds, like this:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (_currentPage == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width) {
scrollView.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);
} else if (_currentPage == totalViewControllersInPageController-1 && scrollView.contentOffset.x > scrollView.bounds.size.width) {
scrollView.contentOffset = CGPointMake(scrollView.bounds.size.width, 0);
}
}
Finally, the implementation for scrollViewWillEndDragging is to deal with a bug scenario when the user quickly swipes from left to right at the first page, the first page won't bounce at the left (due to the function above), but will bounce at the right caused by the (maybe) velocity of the swipe. And finally when bounced back, the UIPageViewController will trigger a page flip to the 2nd page (which is of course, not expected).
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
if (_currentPage == 0 && scrollView.contentOffset.x <= scrollView.bounds.size.width) {
*targetContentOffset = CGPointMake(scrollView.bounds.size.width, 0);
} else if (_currentPage == totalViewControllersInPageController-1 && scrollView.contentOffset.x >= scrollView.bounds.size.width) {
*targetContentOffset = CGPointMake(scrollView.bounds.size.width, 0);
}
}
Code to put into viewDidLoad
:
for subview in self.view.subviews {
if let scrollView = subview as? UIScrollView {
scrollView.delegate = self
break;
}
}
Implementation for scrollViewDidScroll:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (currentPage == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width) {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0);
} else if (currentPage == totalViewControllersInPageController - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width) {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0);
}
}
Implementation for scrollViewWillEndDragging:
func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if (currentPage == 0 && scrollView.contentOffset.x <= scrollView.bounds.size.width) {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0);
} else if (currentPage == totalViewControllersInPageController - 1 && scrollView.contentOffset.x >= scrollView.bounds.size.width) {
targetContentOffset.pointee = CGPoint(x: scrollView.bounds.size.width, y: 0);
}
}
Upvotes: 84
Reputation: 6054
If you will try to disable bounce for UIPageViewController.scrollView
, you will definitely get a broken pageViewController
: swipe ain't gonna work. So, don't do that:
self.theScrollView.alwaysBounceHorizontal = NO;
self.theScrollView.bounces = NO;
Use the solution with searching scrollView
reference in UIPageViewController
subviews only for disabling scroll entirely:
@interface MyPageViewController : UIPageViewController
@property (nonatomic, assign) BOOL scrollEnabled;
@end
@interface MyPageViewController ()
@property (nonatomic, weak) UIScrollView *theScrollView;
@end
@implementation MyPageViewController
- (void)viewDidLoad
{
[super viewDidLoad];
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:UIScrollView.class]) {
self.theScrollView = (UIScrollView *)view;
break;
}
}
}
- (void)setScrollEnabled:(BOOL)scrollEnabled
{
_scrollEnabled = scrollEnabled;
self.theScrollView.scrollEnabled = scrollEnabled;
}
@end
UIScrollView
category (for ex. CustomScrolling). UIScrollView
is delegate of their gesture recognizer already.UIViewController
(aka baseVC
with UIPageViewController
inside) shared via AppDelegate
. Otherwise you can use run-time (#import <objc/runtime.h>
) and add reference property (to your controller baseVC
) to the category.Implement category:
@interface UIScrollView (CustomScrolling) <UIGestureRecognizerDelegate>
@end
@implementation UIScrollView (CustomScrolling)
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
UIViewController * baseVC = [(AppDelegate *)[[UIApplication sharedApplication] delegate] baseVC];
if (gestureRecognizer.view == baseVC.pageViewController.theScrollView) {
NSInteger page = [baseVC selectedIndex];
NSInteger total = [baseVC viewControllers].count;
UIPanGestureRecognizer *recognizer = (UIPanGestureRecognizer *)gestureRecognizer;
CGPoint velocity = [recognizer velocityInView:self];
BOOL horizontalSwipe = fabs(velocity.x) > fabs(velocity.y);
if (!horizontalSwipe) {
return YES;
}
BOOL scrollingFromLeftToRight = velocity.x > 0;
if ((scrollingFromLeftToRight && page > 0) || (!scrollingFromLeftToRight && page < (total - 1))) {
return YES;
}
return NO;
}
return YES;
}
@end
Import category file #import "UIScrollView+CustomScrolling.h"
in your baseVC
, that uses UIPageViewController.
Upvotes: -1
Reputation: 4165
I wasn't sure how to correctly manage the currentIndex
but ended up doing
extension Main: UIPageViewControllerDelegate {
func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed {
guard let viewController = pageViewController.viewControllers?.first,
index = viewControllerDatasource.indexOf(viewController) else {
fatalError("Can't prevent bounce if there's not an index")
}
currentIndex = index
}
}
}
Upvotes: 1
Reputation: 381
Disable UIPageViewController's bounce
Swift 2.2
1) Add UIScrollViewDelegate to UIPageViewController
extension PageViewController: UIScrollViewDelegate
2) Add to viewDidLoad
for view in self.view.subviews {
if let scrollView = view as? UIScrollView {
scrollView.delegate = self
}
}
3) Add UIScrollViewDelegate methods
func scrollViewDidScroll(scrollView: UIScrollView) {
if currentIndex == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
} else if currentIndex == totalViewControllers - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
}
func scrollViewWillEndDragging(scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
if currentIndex == 0 && scrollView.contentOffset.x < scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
} else if currentIndex == totalViewControllers - 1 && scrollView.contentOffset.x > scrollView.bounds.size.width {
scrollView.contentOffset = CGPoint(x: scrollView.bounds.size.width, y: 0)
}
}
Upvotes: 18
Reputation: 13246
UIPageViewController doesn't actually do much for you. You can use a UIScrollView with view controllers quite easily, and disable the bounce on that.
Just do something like
int x=0;
for (NSString *storyboardID in storyboardIDs){
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:storyboardID];
[self addChildViewController:vc];
vc.view.frame = CGRectMake(x++*vc.view.frame.size.width, 0, vc.view.frame.size.width, vc.view.frame.size.height);
[self.scrollView addSubview:vc.view];
[vc didMoveToParentViewController:self];
self.scrollView.contentSize = CGSizeMake(storyboardIDs.count*vc.view.frame.size.width, vc.view.frame.size.height);
}
Upvotes: -1