Member-only story
Android Touch System — Part 3: MotionEvent Listeners
This is Part 3 of my Android Touch System series. Parts 1 and 2 take a deep dive into touch functions (onDispatchTouchEvent()
, onInterceptTouchEvent()
, onTouchEvent()
) and how touch events flow through the view hierarchy. This post will cover the main event listeners provided by the View
class, as well as standalone gesture detector classes.
Table of Contents
- Why Use Listeners?
- OnTouchListener
- OnClickListener
- OnGenericMotionListener
- OnContextClickListener
- GestureDetector
- ScaleGestureDetector
Why Use Listeners?
Most listener interfaces correspond one-to-one with a function in the view class — for example OnTouchListener
with onTouchEvent()
— so when should we use a listener instead of overriding the function directly? There are three considerations:
- Using a listener allows handling touch events without creating a new custom view. If a view has everything you need except event-handling, it’s less verbose to add a listener to your instance of it rather than extending it. For example, if you want a specific
TextView
to open a screen when clicked, setting anOnClickListener
would be simpler than creating aCustomTextView
that extendsTextView
and overridesonTouchEvent()
. - Do other instances of the view require the same event handling? For example, if your app has an
ImageButtonView
that handles a tap differently for each usage, adding a listener to each instance would make sense. But if tapping anImageButtonView
should always open a specific screen, then overridingonTouchEvent()
would be simpler. - The listeners are generally called before the corresponding function, and if the listener returns
true
, the corresponding function won’t be called. Here’s some source code fromView.dispatchTouchEvent()
:
if (li.mOnTouchListener != null
&& li.mOnTouchListener.onTouch(this, event)) {
result = true;
}
if (!result && onTouchEvent(event)) {
result = true;
}
mOnTouchListener.onTouch()
will always run before onTouchEvent()
. If you still want the view’s onTouchEvent()
…