web-dev-qa-db-ja.com

OnTouchEventが子ビューで機能しない

ボタンとTextViewが配置された線形レイアウトがあります。アクティビティのOnTouchEventを作成しました。画面をタッチしてもコードは正常に機能しますが、ボタンをタッチしてもコードは機能しません。これに対する可能な解決策は何ですか?

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


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


   break;
   }
   return true;

  }
28
user1438128

問題は、Androidがタッチイベントを処理する方法の操作の順序です。各タッチイベントは、(簡略化された例)のパターンに従います。

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

しかし、イベントは消費されるまでチェーンに従います(誰かがonTouchEvent()またはリスナーからtrueを返すことを意味します)。画面のどこかにタッチしただけでは、誰もそのイベントに興味がないので、コードに流れていきます。ただし、ボタン(または他のクリック可能なView)の場合は、それに関心があるためタッチイベントを消費し、フローは4行目で停止します。

アクティビティに入るすべてのタッチを監視する場合は、常に呼び出されるものが最初に、アクティビティのdispatchTouchEvent()が最後に呼び出されるため、onTouchEvent()をオーバーライドする必要があります。それ以外の場合はイベントをキャプチャしました。ただし、ここでイベントを消費しないように注意してください。そうしないと、子ビューでイベントが取得されず、ボタンがクリックできなくなります。

_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);
}
_

別のオプションは、タッチ処理コードをカスタムViewGroupLinearLayoutなど)に配置し、そのonInterceptTouchEvent()メソッドを使用して親ビューが離れてタッチを処理できるようにすることです必要に応じてイベント。ただし、この相互作用は、新しいタッチイベントが開始するまで取り消せない相互作用です(1つのイベントを盗んだら、すべてを盗みます)。

HTH

92
Devunwired

@Devunwiredによるこの素晴らしい投稿にコメントをもう1つ追加しましょう。

ビューにonTouchListenerも設定している場合、そのonTouch()メソッドはディスパッチメソッドの後、ただしonTouchEvent()メソッドの前、つまり@Devunwiredの回答のno.3とno.4の間で呼び出されます。

4
kouretinho

レイアウトの descendantFocusability 属性をblocksDescendantsに設定してみてください

1
Jokahero

onUserInteraction()を試すこともできます:

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

私にはうまくいきます!

0
amdev

Activity::onTouchEventは、アクティビティウィンドウ内のビューのいずれもがイベントを消費または処理しない場合にのみ呼び出されます。 Buttonをタッチすると、Buttonがイベントを消費するため、アクティビティはイベントを処理できなくなります。

Androidタッチイベント処理パイプラインの詳細については、以下の記事をご覧ください。

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

0
pierrotlefou

public boolean dispatchTouchEvent(MotionEvent event)ではなくonTouchEvent()を使用してください

0
Asad
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;
    }
});
0
Ray Hulha