Android development-touch Event Processing Mechanism
Android touch message transmission mechanism
Each user touch (onClick, onLongClick, onScroll, etc .) it is composed of one ACTION_DOWN + n ACTION_MOVE + 1 ACTION_UP. A user must first have an ACTION_DOWN response when touching the user, and there must be an ACTION_UP when touching the user. (Of course, if it is intercepted on the way, it may not exist !) So how does View distribute messages and intercept messages?
1. View and its subclass have two methods:
Public boolean dispatchTouchEvent (MotionEvent ev) is used to distribute TouchEvent
Public boolean onTouchEvent (MotionEvent ev) is used to process TouchEvent
2. The special ViewGroup subclass has another method:
Public boolean onInterceptTouchEvent (MotionEvent ev) is used to intercept TouchEvent
3. Distribution
When a touch is received, dispatchTouchEvent transmits a message to the View on the outermost layer, and then distributes the message to the View on the child layer.
4. Interception:
OnInterceptTouchEvent: Return true to intercept the message, and do not pass the message to the subview (the subview here is not an inherited link, but an inclusive link ). If the return value is false, the message is not intercepted. You can continue to send messages to the next View level. The subview can receive the touch message and send the message separately.
5. Message Processing:
OnTouchEvent processes the event, intercepts the message, or the last View that receives the message calls this method to process the event. If true is returned, it indicates that the event is correctly received and processed. If false is returned, it indicates that it is not processed and will be passed to the parent View (the parent View here is not an inherited link, but an inclusive link)
InterceptTouchEvnet and onTouchEvent relationship in Android event model
Reference:
Http://blog.csdn.net/liutao5757124/article/details/6097125
First, read the official Android documentation.
OnInterceptTouchEvent () and onTouchEvent () mechanisms:
1. The down event is first passed to the onInterceptTouchEvent () method.
2. If onInterceptTouchEvent () of the ViewGroup returns false after the down event is processed,
The subsequent move, up, and other events will be passed to the ViewGroup before being passed to the most
OnTouchEvent () processing of the final target view
3. If onInterceptTouchEvent () of the ViewGroup returns true after the down event is received,
The subsequent move and up events will not be passed to onInterceptTouchEvent (), but will be the same as the down event.
The onTouchEvent () process passed to the ViewGroup. Note that the target view will not receive any event.
4. If the onTouchEvent () of the view that finally needs to process the event returns false, the event will be passed to the previous one.
OnTouchEvent () Processing of hierarchical views
5. If the onTouchEvent () of the view that finally needs to process the event returns true, subsequent events can be passed
Process onTouchEvent () of the view
This is the statement in the official document. If I did not write a program to observe it myself, I would not be able to understand it. So I went to the program first and then analyzed it:
Layout file main. xml
Java code
-
- Android: orientation = "vertical" android: layout_width = "fill_parent"
- Android: layout_height = "fill_parent">
- Android: orientation = "vertical" android: layout_width = "fill_parent"
- Android: layout_height = "fill_parent" android: gravity = "center">
- Android: layout_width = "wrap_content" android: layout_height = "wrap_content"
- Android: id = "@ + id/TV" android: text = "AB" android: textSize = "40sp"
- Android: textStyle = "bold" android: background = "# FFFFFF"
- Android: textColor = "# 0000FF"/>
-
-
-
LayoutView1.java
Java code
- Package com. hao;
-
- Import android. content. Context;
- Import android. util. AttributeSet;
- Import android. util. Log;
- Import android. view. MotionEvent;
- Import android. widget. LinearLayout;
-
- Public class LayoutView1 extends LinearLayout {
- Private final String TAG = "LayoutView1 ";
- Public LayoutView1 (Context context, AttributeSet attrs ){
- Super (context, attrs );
- Log. e (TAG, TAG );
- }
-
- @ Override
- Public boolean onInterceptTouchEvent (MotionEvent ev ){
- Int action = ev. getAction ();
- Switch (action ){
- Case MotionEvent. ACTION_DOWN:
- Log. e (TAG, "onInterceptTouchEvent action: ACTION_DOWN ");
- // Return true; this intercepts the event, and the subsequent event will not be obtained.
- Break;
- Case MotionEvent. ACTION_MOVE:
- Log. e (TAG, "onInterceptTouchEvent action: ACTION_MOVE ");
- Break;
- Case MotionEvent. ACTION_UP:
- Log. e (TAG, "onInterceptTouchEvent action: ACTION_UP ");
- Break;
- Case MotionEvent. ACTION_CANCEL:
- Log. e (TAG, "onInterceptTouchEvent action: ACTION_CANCEL ");
- Break;
- }
- Return false;
- }
-
- @ Override
- Public boolean onTouchEvent (MotionEvent ev ){
- Int action = ev. getAction ();
- Switch (action ){
- Case MotionEvent. ACTION_DOWN:
- Log. e (TAG, "onTouchEvent action: ACTION_DOWN ");
- Break;
- Case MotionEvent. ACTION_MOVE:
- Log. e (TAG, "onTouchEvent action: ACTION_MOVE ");
- Break;
- Case MotionEvent. ACTION_UP:
- Log. e (TAG, "onTouchEvent action: ACTION_UP ");
- Break;
- Case MotionEvent. ACTION_CANCEL:
- Log. e (TAG, "onTouchEvent action: ACTION_CANCEL ");
- Break;
- }
- Return true;
- // Return false;
- }
-
- @ Override
- Protected void onLayout (boolean changed, int l, int t, int r, int B ){
- // TODO Auto-generated method stub
- Super. onLayout (changed, l, t, r, B );
- }
-
- @ Override
- Protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec ){
- // TODO Auto-generated method stub
- Super. onMeasure (widthMeasureSpec, heightMeasureSpec );
- }
- }
Layer 2 LayoutView2.java
Java code
- Package com. hao;
-
- Import android. content. Context;
- Import android. util. AttributeSet;
- Import android. util. Log;
- Import android. view. MotionEvent;
- Import android. widget. LinearLayout;
-
- Public class LayoutView2 extends LinearLayout {
-
- Private final String TAG = "LayoutView2 ";
- Public LayoutView2 (Context context, AttributeSet attrs ){
- Super (context, attrs );
- Log. e (TAG, TAG );
- }
-
- @ Override
- Public boolean onInterceptTouchEvent (MotionEvent ev ){
- Int action = ev. getAction ();
- Switch (action ){
- Case MotionEvent. ACTION_DOWN:
- Log. e (TAG, "onInterceptTouchEvent action: ACTION_DOWN ");
- // Return true;
- Break;
- Case MotionEvent. ACTION_MOVE:
- Log. e (TAG, "onInterceptTouchEvent action: ACTION_MOVE ");
- Break;
- Case MotionEvent. ACTION_UP:
- Log. e (TAG, "onInterceptTouchEvent action: ACTION_UP ");
- Break;
- Case MotionEvent. ACTION_CANCEL:
- Log. e (TAG, "onInterceptTouchEvent action: ACTION_CANCEL ");
- Break;
- }
- Return false;
- }
-
- @ Override
- Public boolean onTouchEvent (MotionEvent ev ){
- Int action = ev. getAction ();
- Switch (action ){
- Case MotionEvent. ACTION_DOWN:
- Log. e (TAG, "onTouchEvent action: ACTION_DOWN ");
- Break;
- Case MotionEvent. ACTION_MOVE:
- Log. e (TAG, "onTouchEvent action: ACTION_MOVE ");
- Break;
- Case MotionEvent. ACTION_UP:
- Log. e (TAG, "onTouchEvent action: ACTION_UP ");
- Break;
- Case MotionEvent. ACTION_CANCEL:
- Log. e (TAG, "onTouchEvent action: ACTION_CANCEL ");
- Break;
- }
- // Return true;
- Return false;
- }
- }
-
Custom MyTextView. java
Java code
- Package com. hao;
-
- Import android. content. Context;
- Import android. util. AttributeSet;
- Import android. util. Log;
- Import android. view. MotionEvent;
- Import android. view. View;
- Import android. widget. TextView;
-
- Public class MyTextView extends TextView {
- Private final String TAG = "MyTextView ";
- Public MyTextView (Context context, AttributeSet attrs ){
- Super (context, attrs );
- Log. e (TAG, TAG );
- }
-
- @ Override
- Public boolean onTouchEvent (MotionEvent ev ){
- Int action = ev. getAction ();
- Switch (action ){
- Case MotionEvent. ACTION_DOWN:
- Log. e (TAG, "onTouchEvent action: ACTION_DOWN ");
- Break;
- Case MotionEvent. ACTION_MOVE:
- Log. e (TAG, "onTouchEvent action: ACTION_MOVE ");
- Break;
- Case MotionEvent. ACTION_UP:
- Log. e (TAG, "onTouchEvent action: ACTION_UP ");
- Break;
- Case MotionEvent. ACTION_CANCEL:
- Log. e (TAG, "onTouchEvent action: ACTION_CANCEL ");
- Break;
- }
- Return false;
- // Return true;
- }
-
- Public void onClick (View v ){
- Log. e (TAG, "onClick ");
- }
-
- Public boolean onLongClick (View v ){
- Log. e (TAG, "onLongClick ");
- Return false;
- }
- }
-
In fact, the code is very simple, that is, a custom View. In the View, interceptTouchEvnet (), and onTouchEvent () are rewritten, and then the returned value is tested. The key to the impact on the listener is to do it by yourself, test and predict the results one by one. When you can predict the results, you will understand. The changes are the return values of interceptTouchEvnet and onTouchEvent. They determine the event listening process, I have drawn a picture below. If you have any shortcomings, please correct them. Thank you!
Below is my positive solution:
The basic rule is: * 1. the down event is first passed to the onInterceptTouchEvent () method ** 2. if the onInterceptTouchEvent () of the ViewGroup returns false (not blocked) after the down event is processed, * subsequent move, up, and other events will be passed to the ViewGroup first, the onTouchEvent () process is passed to the final target view just like the down event. ** 3. if the onInterceptTouchEvent () of the ViewGroup returns true after the down event is processed (blocking, the move and up events that follow do not need to be viewed because they have been intercepted, we can directly process onTouchEvent (), so subsequent moving, up and other events will not be passed to onInterceptTouchEvent (), the onTouchEvent () that is passed to the ViewGroup like the down event. Note that the target view will not receive any event. The following example demonstrates the following: * 1: LayoutView1 (31375): onInterceptTouchEvent action: ACTION_DOWN * 2: LayoutView2 (31375): onInterceptTouchEvent action: ACTION_DOWN * 3: LayoutView2 (31375): onTouchEvent action: ACTION_DOWN * 4: LayoutView1 (31375): onInterceptTouchEvent action: ACTION_MOVE * 5: LayoutView2 (31375): onTouchEvent action: ACTION_MOVE * 6: LayoutView1 (31375): Pull action: ACTION_MOVE * 7: layoutView2 (3137 5): onTouchEvent action: ACTION_MOVE * 8: LayoutView1 (31375): onInterceptTouchEvent action: ACTION_UP * 9: LayoutView2 (31375): onTouchEvent action: ACTION_UP * this setting is: * onInterceptTouchEvent: layoutView1 is false, and LayoutView2 is true * onTouchEvent: LayoutView2 is true *. Therefore, the event is intercepted and processed when LayoutView2 (onInterceptTouchEvent: returns true). According to the above statement, LayoutView2 subsequently moves, the UP operation does not pass through onInterceptTouchEvent. The result is also true. (See LayoutView2's 3, 5, 7, and 9. The first onInterceptTouchEvent is processed for example 1, and then handed over to onTouchEvent.) * LayoutView1 still needs to go through onInterceptTouchEvent (see LayoutView1's, 8. if the onTouchEvent () of the view that finally needs to process the event returns false (if the event cannot be processed, the event cannot be dropped back and the parent will continue ), * The event will be passed to the onTouchEvent () processing of the view at the previous level. **************************************** * *********************************** Feels like a circle, then, I am always looking for someone who can process the message. If I find it, it will end. If I don't find it, it will loop until I return to the person who sent the message * Note (for the following ): the unmarked DOWN indicates that the onInterceptTouchEvent is intercepted, and the onTouchEvent is used to process the event *. if not processed (onInterceptTouchEvent returns false): A (DOWN) --> B (DOWN) --> C (onTouchEvent DOWN) --> B (onTouchEvent DOWN) --> A (onTouchEvent DOWN) does not execute the UP event. If you MOVE the event, the following items are the same between DOWN and UP. * B. B processing (B's onInterceptTouchEvent returns true): A (DOWN) --> B (onTouchEvent) --> A (onTouchEvent UP) --> B (onTouchEvent UP) --> (over) * Image Description: if the father does not intercept the message, it will be sent to the son. If the son wants the message, it will be processed (DOWN) and ended, then there is Father 1-Father 2-son to release the message (UP ). However, if the son ignores the message, the message will be sent back to the father, and the father will handle it.
The following figure shows the situation in step 5 (false is returned when onInterceptTouchEvent is not intercepted): * 11 ** Father 1 (LayoutView1 does not intercept false) --- father 2 (LayoutView2 does not intercept false) -- Son (MyTextView, onTouchEvent return true) -- end * 22 ** Father 1 (LayoutView1 does not intercept false) --- father 2 (LayoutView2 does not intercept false) -- Son (MyTextView, onTouchEvent return false) -- return to Father 2 (onTouchEvent return true) -- end * 33 ** Father 1 (LayoutView1 does not intercept false) --- father 2 (LayoutView2 does not intercept false) -- Son (MyTextView, onTouchEvent return false) -- return to Father 2 (onT OuchEvent return false) -- parent 1 (onTouchEvent return true) -- end (if no processing is done, do not execute up action) * 44 ** parent 1 (LayoutView1 blocks true) -- Father 1 (onTouchEvent return true) -- end (DOWN-DOWN (onTouchEvent) -- UP (onTouchEvent) * 55 ** Father 1 (LayoutView1 blocks false) -- Father 2 (LayoutView2 intercept true) -- Father 2 (onTouchEvent return false) -- Father 1 (onTouchEvent return true) -- end (DOWN1--DOWN2--DOWN (2 onTouchEvent) -- DOWN (1 onTouchEvent) -- UP (1 onTouchEvent) (1: Father 2: parent Parent 2) **************************************** * ************************************ 5. if the onTouchEvent () of the view that finally needs to process the event returns true, the subsequent event can be passed to the onTouchEvent () of the view for processing. */
The following is a processing flowchart:
Source code:
- TouchEventTest.rar (94.3 KB)
- Downloads: 40