Mastering the Android Touch System

By: InfoQ

323   3   31003

Uploaded on 01/17/2014

How does Android handle touch? This talk provides an overview of the Android touch framework, gives you an idea of how touches flow through your application, and explains how Android deals with all of these events. Dave Smith, Senior Android Developer with Double Encore and NewCircle Instructor, leads the discussion. Topics covered include:

• Touch System Overview
• Touch Event Framework
• Custom Touch Handling
• System Provided Touch Handlers
• System Provided Gesture Handlers

Dave begins with a thorough jumpstart into the Android touch system, and then dives into the code, in this talk from AnDevCon. If you'd like to learn more, grab a seat in Dave's Android Internals Training Course: http://crcl.to/v9gxg

AnDevCon is returning to SF November '14. Save $200 with discount code: NEWCIRCLE SF -http://crcl.to/AnDevCon

Comments (4):

By anonymous    2017-09-20

Because this is the first result on Google. I want to share with you a great Talk by Dave Smith on Youtube: Mastering the Android Touch System and the slides are available here. It gave me a good deep understanding about the Android Touch System:

How the Activity handles touch:

  • Activity.dispatchTouchEvent()
    • Always first to be called
    • Sends event to root view attached to Window
    • onTouchEvent()
      • Called if no views consume the event
      • Always last to be called

How the View handles touch:

  • View.dispatchTouchEvent()
    • Sends event to listener first, if exists
      • View.OnTouchListener.onTouch()
    • If not consumed, processes the touch itself
      • View.onTouchEvent()

How a ViewGroup handles touch:

  • ViewGroup.dispatchTouchEvent()
    • onInterceptTouchEvent()
      • Check if it should supersede children
      • Passes ACTION_CANCEL to active child
      • Return true once, consumes all subsequent events
    • For each child view, in reverse order they were added
      • If touch is relevant (inside view), child.dispatchTouchEvent()
      • If not handled by previous, dispatch to next view
    • If no children handle event, listener gets a chance
      • OnTouchListener.onTouch()
    • If no listener, or not handled
      • onTouchEvent()
  • Intercepted events jump over child step

He also provides example code of custom touch on github.com/devunwired/.

Answer: Basically the dispatchTouchEvent() is called on every View layer to determine if a View is interested in an ongoing gesture. In a ViewGroup the ViewGroup has the ability to steal the touch events in his dispatchTouchEvent()-method, before it would call dispatchTouchEvent() on the children. The ViewGroup would only stop the dispatching if the ViewGroup onInterceptTouchEvent()-method returns true. The difference is that dispatchTouchEvent()is dispatching MotionEvents and onInterceptTouchEvent tells if it should intercept (not dispatching the MotionEvent to children) or not (dispatching to children).

You could imagine the code of a ViewGroup doing more-or-less this (very simplified):

public boolean dispatchTouchEvent(MotionEvent ev) {
    if(!onInterceptTouchEvent()){
        for(View child : children){
            if(child.dispatchTouchEvent(ev))
                return true;
        }
    }
    return super.dispatchTouchEvent(ev);
}

Original Thread

By anonymous    2017-10-22

Let's take a look at a visual example.

enter image description here

When a touch event occurs, first everyone is notified of the event, starting at the Activity and going all the way to the view on top. Then everyone is given a chance to handle the event, starting with the view on top and going all the way back to the Activity. So the Activity is the first to hear of it and the last to be given a chance to handle it.

enter image description here

If the Activity or some ViewGroup wants to handle the touch event right away (and not give anyone else down the line a chance at it) then it can just return true in its onInterceptTouchEvent().

If a View (or a ViewGroup) has an OnTouchListener, then the touch event is handled by OnTouchListener.onTouch(). Otherwise it is handled by onTouchEvent(). If onTouchEvent() returns true for any touch event, then the handling stops there. No one else down the line gets a chance at it.

More detailed explanation

The above diagram makes things a little more simple than they actually are. For example, between the Activity and ViewGroup A (the root layout) there is also the Window and the DecorView. I left them out above because we generally don't have to interact with them. However, I will include them below. The description below follows a touch event through the source code. You can click a link to see the actual source code.

  1. The Activity's dispatchTouchEvent() is notified of a touch event. The touch event is passed in as a MotionEvent, which contains the x,y coordinates, time, type of event, and other information.
  2. The touch event is sent to the Window's superDispatchTouchEvent(). Window is an abstract class. The actual implementation is PhoneWindow.
  3. The next in line to get the notification is DecorView's superDispatchTouchEvent(). DecorView is what handles the status bar, navigation bar, content area, etc. It is actually just a FrameLayout subclass, which is itself a subclass of ViewGroup.
  4. The next one to get the notification (correct me if I'm wrong) is the content view of your activity. That is what you set as the root layout of your activity in xml when you create the layout in the Android Studio's Layout Editor. So whether you choose a RelativeLayout, a LinearLayout, or a ConstraintLayout, they are all subclasses of ViewGroup. And ViewGroup gets notified of the touch event in dispatchTouchEvent(). This is the ViewGroup A in my diagrams above.
  5. The ViewGroup will notify any children it has of the touch event, including any ViewGroup children. This is ViewGroup B in my diagrams above.
  6. Anywhere along the way, a ViewGroup can short-circuit the notification process by returning true for onInterceptTouchEvent().
  7. Assuming no ViewGroup cut the notifications short, the natural end of the line for the notifications is when the View's dispatchTouchEvent() get's called.
  8. Now it is time, to start handling the events. If there is an OnTouchListener, then it gets the first chance at handling the touch event with onTouch(). Otherwise, the View's onTouchEvent() gets to handle it.
  9. Now all the ViewGroups recursively up the line get a chance to handle the touch event in the same way that View did. Although, I didn't indicate this in the diagram above, a ViewGroup is a View subclass, so everything I described about OnTouchListener.onTouch() and onTouchEvent() also applies to ViewGroups.
  10. Finally, if no one else wanted it, the Activity also gets the last chance to handle the event with onTouchEvent().

FAQ

When would I ever need to override dispatchTouchEvent()?

Probably you wouldn't need to, unless you need to do some extra routing that doesn't occur by default. To monitor touch event notifications, you can override onInterceptTouchEvent() instead.

When would I ever need to override onInterceptTouchEvent()?

If you just want to spy of the touch notifications that are coming in, you can do it here and return false.

However, the main purpose of overriding this method is to let the ViewGroup handle a certain type of touch event while letting the child handle another type. For example, a ScrollView does this to handle scrolling while letting its child handle something like a Button click. Conversely, if the child view doesn't want to let its parent steal its touch event, it can call requestDisallowTouchIntercept().

What are the touch event types?

The main ones are

  • ACTION_DOWN - This is the start of a touch event. You should always return true for the ACTION_DOWN event in onTouchEvent if you want to handle a touch event. Otherwise, you won't get any more events delivered to you.
  • ACTION_MOVE - This event is continuously fired as you move your finger across the screen.
  • ACTION_UP - This is the last event of a touch event.

A runner up is ACTION_CANCEL. This gets called if a ViewGroup up the tree decides to intercept the touch event.

You can view the other kinds of MotionEvents here. Since Android is multi-touch, events are also fired when other fingers ("pointers") touch the screen.

Further study

Original Thread

By anonymous    2017-11-06

For this,You need to understand how touch event work in Android.It is a very broad topic.You need to have proper understanding of `MotionEvent` ,how and when they are triggered.I would recommend you to listen to this talk from Dave Smith on https://www.youtube.com/watch?v=EZAoJU-nUyI&t=3650s

Original Thread

Recommended Books

    Submit Your Video

    If you have some great dev videos to share, please fill out this form.