Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to process all TouchEvents at the ViewGroup level (ie Bubble all events up to containing viewgroup)

I would like to process all touch events at the container level. In other words, I want all touch events to reach the container level. Right now I am finding that TouchEvents only reach the containing ViewGroup if the location of the touch does not land on a UI Component that is contained by the view group. The contained UI Element processes the TouchEvent and it does not bubble up to the container. Does anyone know how to guarantee that all touch events reach the top level container?

Just to be clear, picture an activity with several buttons, several edit texts, and several check boxes. A typical form. Normally I am seeing that each UI component will catch the TouchEvent that lands on it and the container is none the wiser. So I want to know how the container/viewgroup could be informed of all touches that land anywhere within its region whether or not that region is occupied with a button, empty space or an edit text.

like image 630
Code Droid Avatar asked Jul 12 '12 21:07

Code Droid


2 Answers

This is how I interpret your question:

You have View tree like this

  • ViewGroup G
    • View A
    • View B
    • ...

and you want G to handle the MotionEvent created on touch even if it was consumed by any of A, B, ...


How to:

I'll give you two options. Depending on if you want to ignore consumption by

  1. every child
  2. only selected children

use one of the following templates:

  1. Override dispatchTouchEvent() in G

    // In G
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
         super.dispatchTouchEvent(event);
    
         // Handle event here instead of using an OnTouchListener
    
         return true;
     }
    
  2. Override dispatchTouchEvent() in every child whose consumption should be ignored

    • Ignore some children

      // In every child whose consumption should be ignored
      @Override
      public boolean dispatchTouchEvent(MotionEvent event) {
           super.dispatchTouchEvent(ev);
      
           return false; // false means "I did not consume the event"
       }
      
    • Don't forget to setup your listener

      // In G, before touch should be recognized
      setOnTouchListener(new OnTouchListener() {
          @Override
          public boolean onTouch(View v, MotionEvent event) {
              // Handle event here
      
              return true; // true means "I did consume the event"
          }
      });
      

Measured in lines of code, option 1 is a lot simpler. Option 2 is there just in case you need special treatment for some of A, B ...

like image 194
Joel Sjögren Avatar answered Sep 27 '22 20:09

Joel Sjögren


I know it is late, but I think future readers might want to look at ViewGroups.onInterceptTouchEvent().

like image 41
Joffrey Avatar answered Sep 27 '22 21:09

Joffrey