在UIPageViewController中禁用跳动效果

德鲁·K

我已经实现了一个UIPageViewController包含两页的内容。在最右边的页面上,我可以向右滑动,然后将页面向后拉,这样当我释放页面时,它就会弹回。当我向左滑动时,在左页面上也会发生同样的事情。(跳动就像到达野生动物园页面底部时发生的一样)

有没有办法禁用反弹效果?谢谢!

加特伍德

到目前为止,没有任何答案可以完全有效。他们都失败的边缘情况是:

  1. 滚动到第2页。
  2. 用一根手指向页面1拖动。
  3. 将第二只手指放在屏幕上,然后向页面1拖动。
  4. 抬起第一根手指。
  5. 重复直到您拖过第0页。

在这种情况下,到目前为止,我所见过的每个解决方案都超出了页面0的范围。核心问题是底层API被破坏了,并开始报告相对于页面0的内容偏移,而没有调用我们的回调让我们知道它显示了另一个页面。在整个过程中,API仍然声称显示第1页,而实际上是显示在第0页上,而实际上是在第0页,而在第-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对我们说谎,并且行为就像过渡正确完成,将偏移量视为相对于新页面而不是旧页面。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

在UIPageViewController中禁用滑动

来自分类Dev

在ViewPager中实现弹性/弹跳动画效果的最佳方法是什么?

来自分类Dev

在纯CSS中禁用悬停效果

来自分类Dev

在WPF中禁用控件的选择背景效果

来自分类Dev

如何在15.04中禁用窗口效果?

来自分类Dev

在 wordpress 主题 (Bulan) 中禁用标题效果

来自分类Dev

在UIPageViewController中禁用滑动手势

来自分类Dev

禁用UIPageViewController滑动-Swift

来自分类Dev

在跳动中隐藏texfield光标

来自分类Dev

在Windows Phone的ListView中禁用某些项目的倾斜效果

来自分类Dev

如何在离子中禁用IOS平台的滑动效果

来自分类Dev

UIVisualEffectView:在IB中启用活力会禁用模糊效果

来自分类Dev

在Java中禁用按钮时如何摆脱视觉效果

来自分类Dev

如何在Material UI中禁用IconButton波纹效果?

来自分类Dev

在Windows 7中禁用或延迟Alt + Tab Aero Peek效果

来自分类Dev

UIVisualEffectView:在IB中启用鲜艳度会禁用模糊效果

来自分类Dev

禁用Ubuntu 15.10中的所有视觉效果

来自分类Dev

使用CSS转换从屏幕移开时,如何消除跳动效果?

来自分类Dev

Ionic 5 Android无法移除滚动跳动效果

来自分类Dev

图片上的“禁用”效果

来自分类Dev

Safari iOS中的视差滚动跳动

来自分类Dev

如何消除波形中的细微跳动?

来自分类Dev

禁用按钮时禁用悬停效果

来自分类Dev

在Listview上禁用波纹效果

来自分类Dev

jQuery禁用CSS:悬停效果

来自分类Dev

在Android屏幕上禁用效果

来自分类Dev

通过绑定启用/禁用效果

来自分类Dev

禁用动作列表的滚动效果

来自分类Dev

如何使用Bootstrap仅在导航栏中的一项中禁用导航丸悬停效果?

Related 相关文章

热门标签

归档