1. Why do you want to understand the Android event mechanism?
Background: when I was working on the Android project, I encountered a nested relationship like activity - > fragment - > Scrollview - > Button. When everything was ready, the system crashed when I clicked the Button after the program was started. Tencent Button reported the following error when it caught it.
java.lang.IllegalArgumentException
Parameter specified as non-null is null: method kotlin.jvm.internal.Intrinsics.checkParameterIsNotNull, parameter e1
Needless to see, there is a problem with the parameters passed. To solve this problem, you must understand the event distribution mechanism of Android.
2. How to solve.
Let me take a look at an Android event distribution mechanism
As can be seen from the above figure, when clicking a View on Activity, Android shows its complete system default event distribution mechanism Activity - > ViewGroup - > View.
Activity(DispatchTouchEvent)->(VIewGroup)DispatchTouchEvents->(VIewGroup)onInterceptTouchEvent->(view)dispatchTouchEvent->(View)OnTouchEvent
Case 1:
Create a new DispatchEvent project;
Create a new mylinarlayout
class MyLinearLayout(context:Context): LinearLayout(context) { override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { when(ev?.action) { MotionEvent.ACTION_DOWN->{ Log.d("GroupView_dispatchEvent","ACTION_DOWN")} MotionEvent.ACTION_MOVE->{Log.d("GroupView_dispatchEvent","ACTION_MOVE")} MotionEvent.ACTION_UP->{Log.d("GroupView_dispatchEvent","ACTION_UP")} MotionEvent.ACTION_CANCEL->{ (Log.d("GroupView_dispatchEvent","ACTION_CANCEL")) } } return super.dispatchTouchEvent(ev) } override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean { when(ev?.action) { MotionEvent.ACTION_DOWN->{Log.d("GroupView_onIntercept","ACTION_DOWN")} MotionEvent.ACTION_MOVE->{Log.d("GroupView_onIntercept","ACTION_MOVE")} MotionEvent.ACTION_UP->{Log.d("GroupView_onIntercept","ACTION_UP")} MotionEvent.ACTION_CANCEL->{Log.d("GroupView_onIntercept","ACTION_CANCEL")} } return super.onInterceptTouchEvent(ev) } override fun onTouchEvent(event: MotionEvent?): Boolean { when(event?.action) { MotionEvent.ACTION_DOWN->{Log.d("GroupView_onTouchEvent","ACTION_DOWN")} MotionEvent.ACTION_MOVE->{Log.d("GroupView_onTouchEvent","ACTION_MOVE")} MotionEvent.ACTION_UP->{Log.d("GroupView_onTouchEvent","ACTION_UP")} MotionEvent.ACTION_CANCEL->{Log.d("GroupView_onTouchEvent","ACTION_CANCEL")} } return super.onTouchEvent(event) } }
2. Create a new MyButton
class MyButton(context:Context): Button(context) { override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { when(ev?.action) { MotionEvent.ACTION_DOWN->{ Log.d("View_dispatchEvent","ACTION_DOWN")} MotionEvent.ACTION_MOVE->{ Log.d("View_dispatchEvent","ACTION_MOVE")} MotionEvent.ACTION_UP->{ Log.d("View_dispatchEvent","ACTION_UP")} MotionEvent.ACTION_CANCEL->{ Log.d("View_dispatchEvent","ACTION_CANCEL") } } return super.dispatchTouchEvent(ev) } override fun onTouchEvent(event: MotionEvent?): Boolean { when(event?.action) { MotionEvent.ACTION_DOWN->{Log.d("View_onTouchEvent","ACTION_DOWN")} MotionEvent.ACTION_MOVE->{Log.d("View_onTouchEvent","ACTION_MOVE")} MotionEvent.ACTION_UP->{Log.d("View_onTouchEvent","ACTION_UP")} MotionEvent.ACTION_CANCEL->{Log.d("View_onTouchEvent","ACTION_CANCEL")} } Log.d("View_onTouchEvent","I'm the last consumer ${super.onTouchEvent(event)}") return super.onTouchEvent(event) } }
3. Write the following code in MainActivity
class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) var myLinearLayout = MyLinearLayout(this); var myButton = MyButton(this); myButton.setText("MyButton") var viewGroups:ViewGroup.LayoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT); var viewPar:ViewGroup.LayoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT); myLinearLayout.orientation = LinearLayout.VERTICAL; myLinearLayout.addView(myButton,viewPar); setContentView(myLinearLayout,viewGroups); } override fun dispatchTouchEvent(ev: MotionEvent?): Boolean { when(ev?.action) { MotionEvent.ACTION_DOWN->{ Log.d("Activity_dispatchEvent","ACTION_DOWN")} MotionEvent.ACTION_MOVE->{ Log.d("Activity_dispatchEvent","ACTION_MOVE")} MotionEvent.ACTION_UP->{ Log.d("Activity_dispatchEvent","ACTION_UP")} MotionEvent.ACTION_CANCEL->{ Log.d("Activity_dispatchEvent","ACTION_CANCEL") } } return super.dispatchTouchEvent(ev) } override fun onTouchEvent(event: MotionEvent?): Boolean { when(event?.action) { MotionEvent.ACTION_DOWN->{Log.d("Activity_onTouchEvent","ACTION_DOWN")} MotionEvent.ACTION_MOVE->{Log.d("Activity_onTouchEvent","ACTION_MOVE")} MotionEvent.ACTION_UP->{Log.d("Activity_onTouchEvent","ACTION_UP")} MotionEvent.ACTION_CANCEL->{Log.d("Activity_onTouchEvent","ACTION_CANCEL")} } return super.onTouchEvent(event) } }
Click button to observe the printing information
09-29 00:20:11.109 8276-8276/com.example.krcm110.myapplication D/Activity_dispatchEvent: ACTION_DOWN
09-29 00:20:11.116 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_DOWN
09-29 00:20:11.117 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_DOWN
09-29 00:20:11.118 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_DOWN
09-29 00:20:11.118 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_DOWN
09-29 00:20:11.151 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: I'm the last consumer true
09-29 00:20:11.154 8276-8276/com.example.krcm110.myapplication D/Activity_dispatchEvent: ACTION_UP
09-29 00:20:11.154 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_UP
09-29 00:20:11.155 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_UP
09-29 00:20:11.155 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_UP
09-29 00:20:11.155 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_UP
09-29 00:20:11.156 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: I'm the last consumer true
The above is a complete event distribution as shown in Figure 1
4. If we don't release it immediately after clicking and move the mouse, release it again
09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/Activity_dispatchEvent: ACTION_DOWN
09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_DOWN
09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_DOWN
09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_DOWN
09-29 00:30:45.177 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_DOWN
09-29 00:30:45.193 8276-8276/com.example.krcm110.myapplication D / view'ontouchevent: I am the last consumer true09-29 00:30:45.328 8276-8276/com.example.krcm110.myapplication D / activity'dispatchevent: action'move
09-29 00:30:45.328 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_MOVE
09-29 00:30:45.329 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_MOVE
09-29 00:30:45.329 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_MOVE
09-29 00:30:45.329 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_MOVE
I am the last consumer true09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D / activity "dispatchEvent: action" up
09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D/GroupView_dispatchEvent: ACTION_UP
09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D/GroupView_onIntercept: ACTION_UP
09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D/View_dispatchEvent: ACTION_UP
09-29 00:30:45.572 8276-8276/com.example.krcm110.myapplication D/View_onTouchEvent: ACTION_UP
09-29 00:30:45.573 8276-8276/com.example.krcm110.myapplication D / view "ontoucheevent: I am the last consumer true
Summary: the above is a system default Android event mechanism. I believe there are some B numbers in your heart.