微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ios – 禁用UIPageViewController中的反弹效果

参见英文答案 > Disable UIPageViewController bounce7个
我已经实现了一个包含两个页面的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正在向我们说谎,并且表现得像转换正确完成,将偏移量视为相对于新页面而不是旧页面.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐