【问题标题】:How to capture onTouch events on two overlapping views?如何在两个重叠视图上捕获 onTouch 事件?
【发布时间】:2014-12-08 18:05:49
【问题描述】:

布局

!* Container is a relative layout contains two custom views: OuterView1 and InnerView2 * Outer View1 is a custom view, matching the parent’s size (full screen) * Inner View2 is also a custom view, laid on top of OuterView1 overlapping it.

  • Container 是一个相对布局,包含两个自定义视图:OuterView1 和 InnerView2
  • Outer View1 是自定义视图,匹配父级的大小(全屏)
  • Inner View2 也是一个自定义视图,位于 OuterView1 之上,与其重叠。

在 OuterView1 和 InnerView2 上,我想捕获这些触摸事件 onSingleTapConfirmed() 和 onFling()。 OuterView1 和 InnerView2 重叠的区域,我希望将控件传递给两个视图的触摸事件方法。

我试过这个:

容器类

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        outerView1.onTouchEvent(ev);
        innerView2.onTouchEvent(ev);
        return false;
    }

OuterView1 类

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        gesture.onTouchEvent(event);
        return true;
    }

gesture 是 GestureDetector.SimpleOnGestureListener 的一个实例,带有 onDown()、onFling() 和 onSingleTapConfirmed() 方法的日志语句

InnerView2 类

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        gesture.onTouchEvent(event);
        return true;
    }

gesture 是 GestureDetector.SimpleOnGestureListener 的一个实例,带有 onDown()、onFling() 和 onSingleTapConfirmed() 方法的日志语句

使用这种方法,我始终在两个视图的 onDown() 方法中获得回调。但我没有看到 onSingleTapConfirmed() 和 onFling() 方法的一致行为

当我点击红圈(在屏幕截图中)三次时,我得到了三种不同的行为

  • 第一次尝试(期望的行为)

    10-14 09:03:14.155: I/OuterView1(27776): OuterView1.onDown()
    10-14 09:03:14.155: I/InnerView2(27776): InnerView2.onDown()
    10-14 09:03:14.155: W/GestureDetector(27776): [pen gesture] isConsideredDoubleTap - timeout
    10-14 09:03:14.155: I/InnerView2(27776): InnerView2.onDown()
    10-14 09:03:14.460: I/OuterView1(27776): OuterView1.onSingleTapConfirmed()
    10-14 09:03:14.460: I/InnerView2(27776): InnerView2.onSingleTapConfirmed()
    
  • 第二次尝试(只有一个视图获得 onSingleTapConfirmed())

    10-14 09:04:11.615: I/OuterView1(27776): OuterView1.onDown()
    10-14 09:04:11.615: I/InnerView2(27776): InnerView2.onDown()
    10-14 09:04:11.615: W/GestureDetector(27776): [pen gesture] isConsideredDoubleTap - timeout
    10-14 09:04:11.615: I/InnerView2(27776): InnerView2.onDown()
    10-14 09:04:11.915: I/OuterView1(27776): OuterView1.onSingleTapConfirmed()
    
  • 第三次尝试(一个视图获取 onFling(),另一个获取 onSingleTapConfirmed())

    10-14 09:04:04.180: I/OuterView1(27776): OuterView1.onDown()
    10-14 09:04:04.180: I/InnerView2(27776): InnerView2.onDown()
    10-14 09:04:04.180: W/GestureDetector(27776): [pen gesture] isConsideredDoubleTap - timeout
    10-14 09:04:04.180: I/InnerView2(27776): InnerView2.onDown()
    10-14 09:04:04.255: I/InnerView2(27776): InnerView2.onFling()
    10-14 09:04:04.480: I/OuterView1(27776): OuterView1.onSingleTapConfirmed()
    

您能帮我在 OuterView1 和 InnerView2 上捕获触摸事件吗?

【问题讨论】:

    标签: android overlapping touch-event


    【解决方案1】:

    因此,在重叠视图的情况下 - 触摸事件从最上面的孩子分派到后面的那个,然后是第二个孩子后面的另一个,依此类推。 但是,如果最上面的孩子要使用触摸事件(即在接收到它时处理它),那么该视图下面的视图将不会接收到触摸事件。

    如果 onTouchEvent 返回“true”,则它告诉视图管理器它已经处理了触摸并且不希望将事件分派给其他视图。如果您希望该视图下方的视图也接收触摸,那么您希望从 onTouchEvent 为第一个视图返回“false”,在您的情况下为 Innerview。

    另外,在您的代码中,我注意到您正在以编程方式将触摸事件分派给容器类中的 2 个视图。即使仅单击 OuterView,这也会导致 InnerView 接收触摸。如果你想要那个功能,那就没问题了。如果您希望 InnerView 仅在被触摸时获取事件,那么您不希望容器类在这两个视图上显式调用 onTouchEvent。视图层次结构将为您完成。

    关于在两个视图上接收 onFling 或 onSingleTapConfirmed - (假设您想让触摸事件也通过后面的视图,您从 InnerView 的 onTouchEvent 返回“false”)InnerView 已经将事件传递给它背后的视图,因此它不会在手势结束时意识到刚刚发生了一次投掷,对于 onSingleTapConfirmed 也是如此。如果您仍然想获得这些,那么您可能必须在 OuterView 检测到的手势结束时以编程方式调度触摸事件。意思是,如果 OuterView 有一个轻弹手势,那么它也是 InnerView 的轻弹,因此以编程方式使该手势也发生在 InnerView 上。 这是相当复杂的,并且在层次结构中向后调度触摸并不常见。

    希望我没有把你弄糊涂。有不清楚的地方可以追问,我会再试的。

    这会很有帮助:Handling TouchEvents in a ViewGroup

    【讨论】:

    • 您好 Mistwalker,我想在两个视图上接收 onFling() 和 onSingleTapConfirmed()。我只是在尝试多个选项,包括 onInterceptTouchEvent。如果我在最顶部的视图中有底部视图的引用`private View outerView = null;,我就可以让它工作。 public void setOuterView(View outerView) { this.outerView = outerView; } @Override public boolean onTouchEvent(MotionEvent event) { gesture.onTouchEvent(event); if (outerView != null) { outerView.onTouchEvent(event); } 返回真; }` @mistwalker 有没有更好的方法来实现这一点?
    • 我之前评论中的代码搞砸了。此处提供相同的代码:code.google.com/p/ramp-sample/source/browse/android/OverLayView/…
    • 检测到投掷/单击时是否要对 2 个视图执行相同的操作?那么值得将它们重叠在 FrameLayout 中并监听该 FrameLayout 上的手势。否则,如果您想在 2 个视图上观察到相同的触摸事件时做不同的事情,那么是的,您必须以编程方式调度触摸事件。不确定是否有其他方法可以实现这一点。
    • 感谢您的回复。我想在这两个视图上做不同的事情,我将采用我的方法将触摸事件从顶视图分发到它下面的视图。
    猜你喜欢
    • 1970-01-01
    • 2011-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-15
    相关资源
    最近更新 更多