Android OnTouchEvent 不适用于子视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11001282/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 05:41:27  来源:igfitidea点击:

OnTouchEvent not working on child views

androidontouchlistener

提问by user1438128

I have a Linear Layout that has a Button and a TextView on it. I have written a OnTouchEvent for the activity. The code works fine if I touch on the screen, but if I touch the button the code does not work. What is the possible solution for this?

我有一个线性布局,上面有一个 Button 和一个 TextView。我已经为该活动编写了一个 OnTouchEvent。如果我触摸屏幕,代码工作正常,但如果我触摸按钮,代码不起作用。对此的可能解决方案是什么?

public boolean onTouchEvent(MotionEvent event) {
   int eventaction=event.getAction();


   switch(eventaction)
   {
   case MotionEvent.ACTION_MOVE:
      reg.setText("hey");


   break;
   }
   return true;

  }

回答by Devunwired

The problem is the order of operations for how Android handles touch events. Each touch event follows the pattern of (simplified example):

问题在于 Android 如何处理触摸事件的操作顺序。每个触摸事件都遵循以下模式(简化示例):

  1. Activity.dispatchTouchEvent()
  2. ViewGroup.dispatchTouchEvent()
  3. View.dispatchTouchEvent()
  4. View.onTouchEvent()
  5. ViewGroup.onTouchEvent()
  6. Activity.onTouchEvent()
  1. Activity.dispatchTouchEvent()
  2. ViewGroup.dispatchTouchEvent()
  3. View.dispatchTouchEvent()
  4. View.onTouchEvent()
  5. ViewGroup.onTouchEvent()
  6. Activity.onTouchEvent()

But events only follow the chain until they are consumed(meaning somebody returns true from onTouchEvent()or a listener). In the case where you just touch somewhere on the screen, nobody is interested in the event, so it flows all the way down to your code. However, in the case of a button (or other clickable View) it consumes the touch event because it is interested in it, so the flow stops at Line 4.

但是事件只会跟随链直到它们被消耗(意味着有人从onTouchEvent()或监听器返回 true )。如果您只是触摸屏幕上的某处,则没有人对该事件感兴趣,因此它一直流向您的代码。然而,在按钮(或其他可点击的View)的情况下,它消耗触摸事件,因为它对它感兴趣,所以流程在第 4 行停止。

If you want to monitor all touches that go into your Activity, you need to override dispatchTouchEvent()since that what always gets called first, onTouchEvent()for an Activity gets called last, and only if nobody else captured the event. Be careful to not consume events here, though, or the child views will never get them and your buttons won't be clickable.

如果您想监视进入您的 Activity 的所有触摸,您需要覆盖,dispatchTouchEvent()因为它总是首先被调用,onTouchEvent()因为 Activity 被最后调用,并且只有在没有其他人捕获该事件的情况下才被调用。但是请注意不要在此处使用事件,否则子视图将永远无法获取它们并且您的按钮将无法点击。

public boolean dispatchTouchEvent(MotionEvent event) {
   int eventaction=event.getAction();

    switch(eventaction) {
      case MotionEvent.ACTION_MOVE:
          reg.setText("hey");
          break;
      default:
          break;
    }

    return super.dispatchTouchEvent(event);
}

Another option would be to put your touch handling code into a custom ViewGroup(like LinearLayout) and use its onInterceptTouchEvent()method to allow the parent view to steal away and handle touch events when necessary. Be careful though, as this interaction is one that cannot be undone until a new touch event begins (once you steal one event, you steal them all).

另一种选择是将您的触摸处理代码放入自定义ViewGroup(如LinearLayout)并使用其onInterceptTouchEvent()方法允许父视图在必要时窃取并处理触摸事件。不过要小心,因为这种交互在新的触摸事件开始之前无法撤消(一旦你窃取了一个事件,你就窃取了所有事件)。

HTH

HTH

回答by kouretinho

Let me add one more comment to this excellent post by @Devunwired.

让我在@Devunwired 的这篇优秀帖子中再添加一条评论。

If you've also set an onTouchListener on your View, then its onTouch() method will be called AFTER the dispatch methods, but BEFORE any onTouchEvent() method, i.e. in between no.3 and no.4 on @Devunwired's answer.

如果您还在您的视图上设置了一个 onTouchListener,那么它的 onTouch() 方法将在调度方法之后被调用,但在任何 onTouchEvent() 方法之前,即在@Devunwired 的答案中的第 3 和第 4 之间。

回答by Jokahero

Try to set the descendantFocusabilityattribute of your layout to blocksDescendants

尝试将布局的descendantFocusability属性设置为blocksDescendants

回答by pierrotlefou

Activity::onTouchEventwill be called only when non of the views in the Activity WIndow consumes/handles the event. If you touch the Button, the Buttonwill consume the events, so the Activity won't be able to handle it.

Activity::onTouchEvent仅当活动窗口中的所有视图都没有使用/处理事件时才会调用。如果您触摸ButtonButton将消耗事件,因此 Activity 将无法处理它。

Check out following articles for more about Android Touch Event handling pipeline.

查看以下文章,了解有关 Android 触摸事件处理管道的更多信息。

http://pierrchen.blogspot.jp/2014/03/pipeline-of-android-touch-event-handling.html

http://pierrchen.blogspot.jp/2014/03/pipeline-of-android-touch-event-handling.html

回答by amdev

you can also try onUserInteraction():

你也可以尝试onUserInteraction()

@Override 
public void onUserInteraction(){
     //your code here
     super.onUserInteraction();
}

works well for me!

对我来说效果很好!

回答by Asad

use public boolean dispatchTouchEvent(MotionEvent event)instead on onTouchEvent()

使用public boolean dispatchTouchEvent(MotionEvent event)而不是在onTouchEvent()

回答by Ray Hulha

RecyclerView list_view = findViewById(R.id.list_view);
list_view.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener(){
    @Override
    public boolean onInterceptTouchEvent(@NonNull RecyclerView rv, @NonNull MotionEvent e) {
        View child = rv.findChildViewUnder(e.getX(), e.getY());
        Log.i("Hello", "World");
        return false;
    }
});