Skip to main content

Android Touch Framework - I

Let’s start with defining some terms :
  • MotionEvent : Every User event in android is wrapped in the MotionEvent class by the framework. It describes user’s current action as well as other metadata such as touch location, no. of pointers and the time when it occurred.
  • MotionEvents first flow top down in view hierarchy and then come back to the rootview unless they are handled somewhere (explained later) in between. So, a parent always has the control of what to do with an event before sending it to children.
  • Each view/viewgroup has two functions that are involved in touch handling :
    • dispatchTouchEvent : This function is called by a view’s parent to pass it a touch event. The aim of this function is to appropriately route this touch event. It may want to
      • consume this event itself : calls it’s own onTouchEvent method (explained below).
      • pass it to the children : calls child’s dispatchTouchEvent method.
      • a listener : calls listener’s onTouch method if it has been set.
      Remember, it just routes the events, it does NOT do any processing with the event.
    • onTouchEvent : This is the function where the event processing is done.
  • Both dispatchTouchEvent and onTouchEvent return a boolean. They return true if the event was handled/consumed by them, otherwise false. And we know that dispatchTouchEvent either calls child’s dispatchTouchEvent OR it’s own onTouchEvent. So essentially if either of them return true , i.e. consumes the event, it’d return true.
Now let’s use all these concepts.

The first point where the callback comes is Activity’s dispatchTouchEvent method. This is your opportunity to handle any touch event before it’s passed to anywhere else. After this, the activity passes it to the dispatchTouchEvent of the root view.

Now, a root view can be of two types :

View : It checks if there’s a touch listener attached and sends the event if it exists. If it’s not there or if it doesn’t consumes the event, it processes the touch itself i.e. calls its own onTouchEvent method.

ViewGroup : This view has children to manage. So when it receives this callback, it iterates through the list of children to decide who needs this event.
It evaluates this based on the location coordinates of the touch.
  • If there is more than one child who qualifies, it iterates over all of them in the reverse order of how they were added.
  • It can also steal touch events from the children if it needs to process them. E.g Scrollview
This way, the event first bubbles down the view hierarchy and them bubbles up again, unless it’s consumed somewhere in the path.
There’s a lot more to this which I’d be explaining in the next post of this series.
Let me in case of any doubts.
Cheers !

Comments

  1. New casino no deposit bonus codes, promos, free spins, slots - Dr
    Casino No Deposit 오산 출장마사지 Bonuses 2021, Promotions, 포항 출장마사지 Bonus 제주도 출장샵 codes, Free Spins 김해 출장안마 for Real 제주 출장마사지 Money Casino Game Play Online.

    ReplyDelete

Post a Comment

Popular posts from this blog

Android : AbsSavedState cannot be cast to $SavedState

Android AbsSavedState cannot be cast to <View>$SavedState I came across a strange crash today. This is the stacktrace : Fatal Exception: java.lang.ClassCastException: android.view.AbsSavedState$1 cannot be cast to android.widget.ScrollView$SavedState at android.widget.ScrollView.onRestoreInstanceState(ScrollView.java:1810) at android.view.View.dispatchRestoreInstanceState(View.java:14768) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:3123) at android.view.View.restoreHierarchyState(View.java:14746) at android.support.v4.app.Fragment.restoreViewState(SourceFile:470) at android.support.v4.app.FragmentManagerImpl.moveToState(SourceFile:1326) at android.support.v4.app.FragmentManagerImpl.moveFragmentsToInvisible(SourceFile:2323) at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(SourceFile:2136) at android.support.v4.app.FragmentManagerImpl.optimizeAndExecuteOps(SourceFile:2092)

Android Tip : Handling back button in Fragments

Android Tip : Handling hardware back button in Fragment and DialogFragment This post explains how to handle hardware back button in a Fragment OR DialogFragment . In DialogFragment, it’s quiet straight forward to achieve this. You’ve to get the dialog instance and set onKeyListener on it : if (getDialog() != null ) { getDialog().setOnKeyListener( new DialogInterface.OnKeyListener() { @Override public boolean onKey (DialogInterface dialog, int keyCode, KeyEvent event) { if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) { Timber.i( "hardware back button pressed" ); } } }); } This can be done in the onViewCreated callback. For fragments, this method doesn’t work and fragments doesn’t have a direct callback to catch this event. So in this case, the approach that we follow is : You

DialogFragment : NullPointerException (support library)

Another weird crash this time ! Here’s the stack trace : Fatal Exception: java.lang.RuntimeException: Unable to start activity ComponentInfo{<activity.fully.qualified.path>}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Dialog.setContentView(android.view.View)' on a null object reference at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2659) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2724) at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:4524) at android.app.ActivityThread.-wrap19(ActivityThread.java) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1479) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6123) at java.lang.reflect.Method.invoke(Method.java) at com.android