参见英文答案 >
Disable UIPageViewController bounce7个
我已经实现了一个包含两个页面的UIPageViewController.在最右边的页面上,我可以向右滑动,并将页面向后拉,以便当我释放时,它会弹回.当我向左滑动时,左侧页面上会出现同样的情况. (弹跳就像当你到达safari页面的底部时会发生什么)
我已经实现了一个包含两个页面的UIPageViewController.在最右边的页面上,我可以向右滑动,并将页面向后拉,以便当我释放时,它会弹回.当我向左滑动时,左侧页面上会出现同样的情况. (弹跳就像当你到达safari页面的底部时会发生什么)
有没有办法禁用弹跳效果?谢谢!
解决方法
到目前为止,没有一个答案实际上完全有效.他们都失败的边缘案例是:
>滚动到第2页.
>使用一根手指拖到第1页.
>将第二根手指放在屏幕上,然后拖到第1页.
>提起第一根手指.
>重复,直到你已经拖过页面0.
在这种情况下,我看到的每个解决方案到目前为止,都超过了第0页的界限.核心问题是底层API被破坏,并开始报告相对于第0页的内容偏移量,而不用调用回调来让我们知道它显示不同的页面.在整个这个过程中,API仍然声称显示第1页,即使在第零页进入第-1页时,页面零.
这种设计缺陷的解决方法非常丑陋,但这里是:
@property (weak,nonatomic) UIPageControl *pageControl; @property (nonatomic,assign) BOOL shouldBounce; @property (nonatomic,assign) CGFloat lastPosition; @property (nonatomic,assign) NSUInteger currentIndex; @property (nonatomic,assign) NSUInteger nextIndex; - (void)viewDidLoad { [super viewDidLoad]; ... self.shouldBounce = NO; for (id testView in self.pageController.view.subviews) { UIScrollView *scrollView = (UIScrollView *)testView; if ([scrollView isKindOfClass:[UIScrollView class]]) { scrollView.delegate = self; // scrollView.bounces = self.shouldBounce; } } } - (NSInteger)presentationIndexForPageViewController:(UIPageViewController *)pageViewController{ return (NSInteger)self.currentIndex; } - (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers{ id controller = [pendingViewControllers firstObject]; self.nextIndex = [viewControllers indexOfObject:controller]; } - (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished prevIoUsViewControllers:(NSArray *)prevIoUsViewControllers transitionCompleted:(BOOL)completed{ if(completed) { // At this point,we can safely query the API to ensure // that we are fully in sync,just in case. self.currentIndex = [viewControllers indexOfObject:[pageViewController.viewControllers objectAtIndex:0]]; [self.pageControl setCurrentPage:self.currentIndex]; } self.nextIndex = self.currentIndex; } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { /* The iOS page view controller API is broken. It lies to us and tells us that the currently presented view hasn't changed,but under the hood,it starts giving the contentOffset relative to the next view. The only way to detect this brain damage is to notice that the content offset is discontinuous,and pretend that the page changed. */ if (self.nextIndex > self.currentIndex) { /* Scrolling forwards */ if (scrollView.contentOffset.x < (self.lastPosition - (.9 * scrollView.bounds.size.width))) { self.currentIndex = self.nextIndex; [self.pageControl setCurrentPage:self.currentIndex]; } } else { /* Scrolling backwards */ if (scrollView.contentOffset.x > (self.lastPosition + (.9 * scrollView.bounds.size.width))) { self.currentIndex = self.nextIndex; [self.pageControl setCurrentPage:self.currentIndex]; } } /* Need to calculate max/min offset for *every* page,not just the first and last. */ CGFloat minXOffset = scrollView.bounds.size.width - (self.currentIndex * scrollView.bounds.size.width); CGFloat maxXOffset = (([viewControllers count] - self.currentIndex) * scrollView.bounds.size.width); NSLog(@"Page: %ld NextPage: %ld X: %lf MinOffset: %lf MaxOffset: %lf\n",(long)self.currentIndex,(long)self.nextIndex,(double)scrollView.contentOffset.x,(double)minXOffset,(double)maxXOffset); if (!self.shouldBounce) { CGRect scrollBounds = scrollView.bounds; if (scrollView.contentOffset.x <= minXOffset) { scrollView.contentOffset = CGPointMake(minXOffset,0); // scrollBounds.origin = CGPointMake(minXOffset,0); } else if (scrollView.contentOffset.x >= maxXOffset) { scrollView.contentOffset = CGPointMake(maxXOffset,0); // scrollBounds.origin = CGPointMake(maxXOffset,0); } [scrollView setBounds:scrollBounds]; } self.lastPosition = scrollView.contentOffset.x; } - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVeLocity:(CGPoint)veLocity targetContentOffset:(inout CGPoint *)targetContentOffset { /* Need to calculate max/min offset for *every* page,not just the first and last. */ CGFloat minXOffset = scrollView.bounds.size.width - (self.currentIndex * scrollView.bounds.size.width); CGFloat maxXOffset = (([viewControllers count] - self.currentIndex) * scrollView.bounds.size.width); if (!self.shouldBounce) { if (scrollView.contentOffset.x <= minXOffset) { *targetContentOffset = CGPointMake(minXOffset,0); } else if (scrollView.contentOffset.x >= maxXOffset) { *targetContentOffset = CGPointMake(maxXOffset,0); } } }
基本上,它记录每个滚动事件的偏移量.如果滚动位置与滚动方向相反的方向移动了一个不可能的距离(我任意挑选屏幕宽度的90%),代码假定iOS正在向我们说谎,并且表现得像转换正确完成,将偏移量视为相对于新页面而不是旧页面.