【问题标题】:How to tell whether a UIPageViewController page turn is due to a swipe/pan or a tap如何判断 UIPageViewController 翻页是由于滑动/平移还是点击
【发布时间】:2019-07-19 06:39:41
【问题描述】:

使用 UIPageViewController 时,用户可以向右或向左滑动以创建跟随手指的动画翻页。或者用户可以简单地点击页面视图的一侧或另一侧来导致翻页。翻页动画完成后,会调用委托方法pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted:方法。

我希望我的最终页面状态略有不同,具体取决于用户是通过滑动还是点击来翻页。但我无法找到一种可靠的方法来确定导致翻页的原因。 pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted: 方法不提供该信息。

在我的 UIPageViewController 委托 (self) 中,调用了 gestureRecognizer:shouldReceiveTouch: 方法,但即使用户最终只使用一种或另一种手势,滑动(平移)和点击手势识别器也会调用它.代表手势方法在屏幕被触摸的那一刻被调用。所以这无济于事。

我在页面视图中添加了一组与触摸相关的拦截方法。对于touchesBegan:withEvent:,我重置了一个标志。对于touches:moved:,它不需要点击手势,我设置了标志。这种方法有效,但它的级别太低了,将来可能无法正常工作,因为它也可以移动,但不是滑动/平移。而且 UIPageViewController 的点击手势似乎完全吞噬了触摸事件,所以甚至没有调用 touchesBegan:withEvent:(这很奇怪)。

有什么方法可以可靠地区分 UIPageViewController 使用哪种翻页方式(点击或平移/滑动)来处理用户翻页的交互? p>

【问题讨论】:

    标签: ios cocoa-touch uigesturerecognizer uipageviewcontroller


    【解决方案1】:

    gestureRecognizer:shouldReceiveTouch: 你可以查看手势类型。

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        if gestureRecognizer is UITapGestureRecognizer {
           self.wasTap = true;
           self.wasSwipe = false;
        } else if gestureRecognizer is UISwipeGestureRecognizer {
           self.wasTap = false;
           self.wasSwipe = true;
        }
        return true;
    }
    

    然后在pageViewController:didFinishAnimating:previousViewControllers:transitionCompleted: 中根据布尔值为 true 更改最终页面的状态。

    【讨论】:

    • 我不明白这是怎么回事。正如我在问题中所说,为 both 类型的手势调用了 gestureRecognizer:shouldReceiveTouch: 委托方法。如果这两个调用的顺序取决于最终使用的手势类型,那么人们可能会收集到哪个手势负责。但是这两个调用都发生在点击或滑动手势开始的那一刻,大概是因为页面视图控制器的所有手势识别器都被调用,而不管最终识别器的类型决定点击和滑动。所以这个顺序是任意的(苹果方面没有记录)。
    • 为了澄清我之前的评论,gestureRecognizer:shouldReceiveTouch: 委托方法似乎为与 UIPageViewController 关联的所有手势识别器调用。所以上面的建议只会根据提供的 last 手势识别器设置标志,并且不能保证所有手势识别器的迭代顺序。无论如何,即使知道顺序,也没关系,因为手势识别器还没有弄清楚哪一个最终会赢得开始翻页。
    【解决方案2】:

    问题实际上是如何确定几个手势识别器中的哪一个对发生的事情负责。

    要理解的关键是任何手势识别器都可以安装多个目标/动作。 UIPageViewController 在内部设置自己的目标/动作,但这并不排除添加其他对象。

    在加载或实例化 UIPageViewController 后设置子类时,添加以下代码(或等效的 Swift 代码):

    for (UIGestureRecognizer *gr in self.gestureRecognizers) {
        if ([gr class] == [UIPanGestureRecognizer class])
            [gr addTarget:self action:@selector(panGestureOccurred)];
         else if ([gr class] == [UITapGestureRecognizer class])
            [gr addTarget:self action:@selector(tapGestureOccurred)];
        }
    

    然后,将两个目标/动作方法添加到子类中:

    - (void)tapGestureOccurred
    {
        // Set a flag here to rely on later after the page turn
    }
    
    - (void)panGestureOccurred
    {
        // Reset a flag here to rely on later after the page turn
    }
    

    这显然适用于任何其他类型的手势,但目前UIPageViewController 似乎只支持平移和点击手势。

    panGestureOccurred 将在用户触摸屏幕并移动手指/触控笔时被多次调用。 tapGestureOccurred 只被调用一次。

    但是这两种方法中只有一种会被调用,这取决于页面视图控制器以其无限智慧决定获胜的手势识别器。这一切似乎比原始问题中提出的太低级别的touchesBegantouchesMoved 想法更有效。

    【讨论】:

    • “要理解的关键是任何手势识别器都可以安装多个目标/动作。”这条线节省了我的时间。 +1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-16
    • 1970-01-01
    • 2021-11-17
    相关资源
    最近更新 更多