【问题标题】:iOS: send touch events to view behind if touch is within specific areaiOS:如果触摸在特定区域内,则将触摸事件发送到后面查看
【发布时间】:2019-07-11 13:47:16
【问题描述】:

我有一个包含一些自定义 UI 控件的视图 A。视图 A 大于屏幕上显示的 UI 控件。视图 A 位于 ViewController A 中,它位于 ViewController B 之上(VC B 是 VC A 的属性)。 我想告诉我的手势识别器,当用户在视图 A 的特定区域内点击时,视图 A 根本不应该响应触摸事件,而是应该由 VC B 中的视图消费和处理。

一旦用户在视图 A 的特定区域内触摸,我尝试将 isUserInteractionEnabled 设置为 false,以便视图 A(或 VC A)后面的视图自动处理触摸事件。 问题是,isUserInteractionEnabled 设置为 false,我不再能够响应视图 A 正确区域中的触摸事件。

只有当视图 A 位于视图 A 的特定区域时,是否有更好的方法将触摸事件发送到视图 A 后面的视图?

【问题讨论】:

    标签: ios swift uiview uigesturerecognizer touch-event


    【解决方案1】:

    您可以重写pointInside 方法,使控制器A 中的视图A 避免处理事件,效果就像isUserInteractionEnabled 所做的那样。而且您还将有一种计算特定面积的方法。

    例子:

    class ViewA: UIView{
        override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
            //assume this area has no response
            let areaNoResponses = CGRect(x: 10, y: 10, width: 100, height: 100) 
    
            if (areaNoResponses.contains(point)) {
                return false;  //no response, like ViewA.isUserInteractionEnabled = NO
            }
            return true;
        }
    }
    

    【讨论】:

    • 什么时候调用这个方法?此外,在运行时,我想让视图 A 覆盖全屏,并显示更多 UIControls。那将需要我更改areaNoResponses。因为 viewA 有动画,所以我需要一种方法来在动画开始时触发对 point() 的调用。
    • pointInside 方法将在用户触摸屏幕时自动调用。当touch事件发生时,系统会按照这个顺序传递事件:UIApplication->UIViewController->UIView,所以大部分UIView都有机会告诉系统它是否会处理这个事件,也就是pointInside或者hitTest的工作。对于动画等情况,你可以为areaNoResponses提供一个属性,并在区域改变时改变它。
    【解决方案2】:

    VC B 是 VC A 的属性

    我假设 VC B 是 VC A 的子视图控制器。 现在,如果视图 A 掩盖了 VC B 的视图,那么您别无选择,只能让视图 A 响应触摸。同样,如果这些是分离的视图控制器和分离的视图,点击视图 A 将始终使其响应触摸。

    您可以做的就是准确检测您希望 VC B 的视图何时响应视图 A 上的触摸并将所需信息传递给 VC B。VC B 中的函数将按照您的意图执行所需的任务。

    例子:

    VC A:
    let tapGesture = UITapGestureRecognizer(target:action:)
    viewA.addGestureRecognizer(tapGesture)
    
    @objc func handleTap(_ sender: UITapGestureRecognizer) {
        //Assuming VC B has been initialized beforehand
        vcB.handleGestureFromVCA()
    }
    
    VC B:
    
    @objc func handleGestureFromVCA() {
        // Code for VC B's views go here
    }
    

    希望这会有所帮助。如果没有,请与我们分享您的尝试。

    【讨论】:

    • 这种方法可行,但需要大量工作。 ViewController A 有一个 MiniPlayer(如 Apple Music 应用程序)并位于 tapviewcontroller 之上。因此,将触摸事件传递给点击控制器上的每个选项卡并手动响应这些触摸事件会导致大量工作。
    • 你可以做一件事来减少工作量。 您可以制作一个主视图控制器,其中包含一些常用方法和 UI 元素(请记住为此编写代码。Outlets 会导致崩溃)。 然后在主视图控制器的子类中,例如@ 987654323@ 和 VC B override 响应触摸的常用函数。你可以通过notification center 实现一个监听器并在触摸时发布。
    猜你喜欢
    • 2012-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-16
    相关资源
    最近更新 更多