When you touch the screen of an Android device, the android system creates a motionevent object.
A motionevent object describes a set of event sequences related to user touch. It contains information such as the touch position, time, and action.
When a touch occurs, the motionevent object is passed to the appropriate method as a method parameter (usually a callback method ).
The getaction () method describes the current action:
Action_down: Finger press value: 0action_move: finger movement value: 2action_up: Finger bounce value: 1
The ontouch () callback method of ontouchlistener accepts a motionevent generated by the system. The returned value of this callback method is boolean. If true is returned, the view that implements ontouchlistener will tell Android: I am not interested in the touch event sequence and the touch event sequence that will occur in the future. Please look for the next view that you are interested in. The next time the Android system receives a touch event, it does not send the instance of motionevent to this view. Instead, it looks for the next view that accepts the motionevent. The first and second motionevents are the same object rather than the new one (the following example will verify this statement)
The following is a demo:
Layout file: activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity" > <RelativeLayout android:id="@+id/truelayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/black" android:layout_weight="1" android:tag="truelayout" > <com.example.mytouchdemo.TrueButton android:id="@+id/truebutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/white" android:tag="truebutton" android:text="true" /> <com.example.mytouchdemo.FalseButton android:id="@+id/falsebutton" android:layout_below="@+id/truebutton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/white" android:tag="falsebutton" android:text="false" /> </RelativeLayout> <RelativeLayout android:id="@+id/falselayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:tag="falselayout" android:background="@android:color/darker_gray" > <com.example.mytouchdemo.TrueButton android:id="@+id/falsebutton2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/white" android:tag="falsebutton2" android:text="false" /> </RelativeLayout></LinearLayout>
Truebutton and falsebutton are both custom controls that inherit booleanbutton and booleanbutton
The ontouchevent callback of booleanbutton receives the motionevent object. The returned value depends on whether it is truebutton. Or falsebutton ..
public abstract class BooleanButton extends Button { protected boolean myValue() { return false; }public BooleanButton(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.v(tag, "------"+ getTag() +"--------------"); Log.v(tag, "action:" + event.getAction()); Log.v(tag, "and I'm returning " + myValue()); Log.v(tag, "MotionEvent's hashcode="+event.hashCode()+""); return(myValue());}private String tag = "test";}
public class TrueButton extends BooleanButton { protected boolean myValue() { return true; } public TrueButton(Context context, AttributeSet attrs) {super(context, attrs);}}
public class FalseButton extends BooleanButton {public FalseButton(Context context, AttributeSet attrs) {super(context, attrs);}}
Mainactivity. Java
Public class mainactivity extends activity implements ontouchlistener {@ overrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); // the layout of the upper part. The ontouch method returns truerelativelayout truelayout = (relativelayout) findviewbyid (R. id. truelayout); // true button, the ontouch Method and Its ontouchevent method return truebutton = (button) findviewbyid (R. id. truebutton); // false button, the ontouch Method and Its ontouchevent method return falsebutton = (button) findviewbyid (R. id. falsebutton); button falsebutton2 = (button) findviewbyid (R. id. falsebutton2); // the lower half layout. The ontouch method returns falserelativelayout falselayout = (relativelayout) findviewbyid (R. id. falselayout); // registers the ontouch event truelayout. setontouchlistener (this); falselayout. setontouchlistener (this); truebutton. setontouchlistener (this); falsebutton. setontouchlistener (this); falsebutton2.setontouchlistener (this) ;}@ overridepublic Boolean ontouch (view V, motionevent event) {string tagstr = v. gettag (). tostring (). substring (0, 4); // The control whose first 4 digits are true. ontouch returns true; otherwise, falseif ("true ". equals (tagstr) {log. V (TAG, "------" + v. gettag () + "--------------"); log. V (TAG, "Action:" + event. getaction (); log. V (TAG, "and I'm returning" + tagstr); log. V (TAG, "motionevent's hashcode =" + event. hashcode () + ""); Return true;} else {return false ;}} string tag = "test ";}
Start the program now, click truebutton in the upper-left layout, and check the logcat output:
06-17 22:26:31. 662: V/test (5766): ------ truebutton --------------
06-17 22:26:31. 662: V/test (5766): Action: 0
06-17 22:26:31. 662: V/test (5766): And I'm returning true
06-17 22:26:31. 662: V/test (5766): motionevent's hashcode = 1097894832
06-17 22:26:31. 682: V/test (5766): ------ truebutton --------------
06-17 22:26:31. 682: V/test (5766): Action: 2
06-17 22:26:31. 682: V/test (5766): And I'm returning true
06-17 22:26:31. 682: V/test (5766): motionevent's hashcode = 1097894832
06-17 22:26:31. 702: V/test (5766): ------ truebutton --------------
06-17 22:26:31. 702: V/test (5766): Action: 2
06-17 22:26:31. 702: V/test (5766): And I'm returning true
06-17 22:26:31. 702: V/test (5766): motionevent's hashcode = 1097894832
06-17 22:26:31. 712: V/test (5766): ------ truebutton --------------
06-17 22:26:31. 712: V/test (5766): Action: 1
06-17 22:26:31. 712: V/test (5766): And I'm returning true
06-17 22:26:31. 712: V/test (5766): motionevent's hashcode = 1097894832
All events are received in truebutton, including pressing action: 0, Moving action: 2, and popping action: 1. This is because the ontouch method returns true.
Now, click the falsebutton in the upper part of the layout to check the logcat output:
06-17 22:29:06. 892: V/test (5766): ------ falsebutton --------------
06-17 22:29:06. 892: V/test (5766): Action: 0
06-17 22:29:06. 892: V/test (5766): And I'm returning false
06-17 22:29:06. 892: V/test (5766): motionevent's hashcode = 1097894832
06-17 22:29:06. 892: V/test (5766): ------ truelayout --------------
06-17 22:29:06. 892: V/test (5766): Action: 0
06-17 22:29:06. 902: V/test (5766): And I'm returning true
06-17 22:29:06. 902: V/test (5766): motionevent's hashcode = 1097894832
06-17 22:29:06. 912: V/test (5766): ------ truelayout --------------
06-17 22:29:06. 912: V/test (5766): Action: 2
06-17 22:29:06. 912: V/test (5766): And I'm returning true
06-17 22:29:06. 912: V/test (5766): motionevent's hashcode = 1097894832
06-17 22:29:06. 932: V/test (5766): ------ truelayout --------------
06-17 22:29:06. 932: V/test (5766): Action: 2
06-17 22:29:06. 932: V/test (5766): And I'm returning true
06-17 22:29:06. 932: V/test (5766): motionevent's hashcode = 1097894832
06-17 22:29:06. 952: V/test (5766): ------ truelayout --------------
06-17 22:29:06. 952: V/test (5766): Action: 2
06-17 22:29:06. 952: V/test (5766): And I'm returning true
06-17 22:29:06. 952: V/test (5766): motionevent's hashcode = 1097894832
06-17 22:29:06. 972: V/test (5766): ------ truelayout --------------
06-17 22:29:06. 972: V/test (5766): Action: 1
06-17 22:29:06. 972: V/test (5766): And I'm returning true
06-17 22:29:06. 972: V/test (5766): motionevent's hashcode = 1097894832
The falsebutton and the layout truelayout both receive the push event, but the subsequent movement and bounce events are only received by truelayout. Because falsebutton returns false in ontouch, which indicates that it no longer receives the subsequent touch time and is processed by other views, the android system finds truelayout, because the ontouch of truelayout returns true, so it handles all the touch event sequences. It is also noted that the hashcode of the motionevent received twice is the same, indicating that they are a motionevent.
Click the falsebutton in the lower half of the layout and logcat output:
06-17 22:36:57. 942: V/test (7164): ------ falsebutton2 --------------
06-17 22:36:57. 942: V/test (7164): Action: 0
06-17 22:36:57. 942: V/test (7164): And I'm returning false
06-17 22:36:57. 942: V/test (7164): motionevent's hashcode = 1098095696
We can see that it is very tragic, because the layout containing falselayout also returns false. Currently, no view can receive the motionevent object, so we cannot listen to the moving and popping events.
Next, let's look at a special situation: Hold down the truebutton in the upper part and move your finger until you remove the button and move it to relativelayout. View log:
06-17 22:39:41. 442: V/test (7164): ------ truebutton --------------
06-17 22:39:41. 442: V/test (7164): Action: 0
06-17 22:39:41. 442: V/test (7164): And I'm returning true
06-17 22:39:41. 442: V/test (7164): motionevent's hashcode = 1098095696
06-17 22:39:41. 462: V/test (7164): ------ truebutton --------------
06-17 22:39:41. 462: V/test (7164): Action: 2
06-17 22:39:41. 462: V/test (7164): And I'm returning true
06-17 22:39:41. 462: V/test (7164): motionevent's hashcode = 1098095696
......................................................
You will find that the range of the button is calculated. It still listens to the touch event. This is because it returns true, which means that all the touch actions are handled by me. This is also the meaning of the "Touch sequence ".