Three monitoring methods have been implemented in Android touch messages:
1) pre-pressed: the semantics is that the user clicks the screen.
2) pressed: the semantics is that the user clicks the screen.
3) long pressed: the semantics is that the user presses the screen by a long press.
Is the timeline of the touch message that changes over time:
T0 and T1 are defined in the viewconfiguration class, which identifies the time-out periods of TAP and longpress. The definitions are as follows:
/** * Defines the duration in milliseconds we will wait to see if a touch event * is a tap or a scroll. If the user does not move within this interval, it is * considered to be a tap. */ private static final int TAP_TIMEOUT = 115; // t0 /** * Defines the duration in milliseconds before a press turns into * a long press */ private static final int LONG_PRESS_TIMEOUT = 500; // t1
In the ontouchevent function of the View class where monitoring is implemented in the Code, when the view detects the action_down event, it first sends an asynchronous message with a latency of T0. The Code is as follows:
Case motionevent. action_down: If (mpendingcheckfortap = NULL) {mpendingcheckfortap = new checkfortap ();} mprivateflags | = prepressed; mhas#medlongpress = false; postdelayed (mpendingcheckfortap, viewconfiguration. gettaptimeout (); break;
If the user releases the screen within T0, that is, the action_up event occurs within T0, the current touch corresponds to the pre-pressed processing code, and the semantics is "User touch (TAP) the screen is released. If you release the screen within T1, this operation is a "Press" operation. If you release the screen more than T1, the system considers that the long-cycle event is monitored. The code that processes the "Press" operation is in the checkfortap class, and the code that processes the long-pressed operation is in the checkforlongpress class. The code for processing pre-pressed is in the action_up Event Response. Most of the Code in the action_up event response is used to handle changes in the touch status, as shown below:
Case motionevent. action_up: Boolean prepressed = (mprivateflags & prepressed )! = 0; // get the prepressed status if (mprivateflags & pressed )! = 0 | prepressed) {// if it is in the pressed or prepressed status, it is processed. // if the current view does not have focus, you need to obtain the focus first, because we currently process the touch mode Boolean focustaken = false; If (isfocusable () & isfocusableintouchmode ()&&! Isfocused () {focustaken = requestfocus (); // requests get focus} If (! Mhasperformedlongpress) {// whether the processing is too long by operation. If yes, the system returns // to the code segment. This indicates that this is a tap operation. First, remove the long by callback operation removelongpresscallback (); // only perform take click actions if we were in the pressed state if (! Focustaken) {// use a runnable and post this rather than calling // specify mclick directly. this lets other visual state // Of the view update before click Actions start. if (mperformclick = NULL) {mperformclick = new multiple mclick ();} If (! Post (mperformclick) {processing mclick (); // The processing function for executing the click }}if (munsetpressedstate = NULL) {munsetpressedstate = new unsetpressedstate ();} If (prepressed) {mprivateflags | = pressed; refreshdrawablestate (); // send the asynchronous delayed message postdelayed (munsetpressedstate, viewconfiguration. getpressedstateduration ();} else if (! Post (munsetpressedstate) {// If the post failed, unpress right now munsetpressedstate. Run () ;}removetapcallback (); // remove the callback operation of the TAP} break;
In the code analysis above, we can see that the whole monitoring process involves two runnable objects and a function that uses handler to send asynchronous delayed messages. The following is an analysis:
1) postdelayed Function
The main task of this function is to obtain the handler object of the UI thread, and then call the postdelayed function of the handler class to put the specified runnable object into the message queue.
Public Boolean postdelayed (runnable action, long delaymillis) {handler; If (mattachinfo! = NULL) {handler = mattachinfo. mhandler;} else {// assume that post will succeed later viewroot. getrunqueue (). postdelayed (action, delaymillis); Return true;} return handler. postdelayed (action, delaymillis );}
2) checkfortap class
This class implements the runnable interface, sets the touch identifier in the run function, refreshes the drawable status, and sends an asynchronous delayed message for detecting long-pressed events. The Code is as follows:
Private final class checkfortap implements runnable {public void run () {// enter this function, indicating that viewconfiguration has passed. gettaptimeout () time, // that is, the pre-pressed State ends, and the touch enters the pressed state mprivateflags & = ~ Prepressed; mprivateflags | = pressed; refreshdrawablestate (); // refresh the background drawable of the control // if the force is not enabled, send an asynchronous delayed message if (mviewflags & long_clickable) = long_clickable) {postcheckforlongclick (viewconfiguration. gettaptimeout () ;}} private void postcheckforlongclick (INT delayoffset) {mhasperformedlongpress = false; // instantiate the checkforlongpress object if (mpendingcheckforlongpress = NULL) {mpendingcheckforlongpress = new checkforlongpress ();} mpendingcheckforlongpress. rememberrentwattachcount (); // call the postdelayed function to send the asynchronous delayed message postdelayed (mpendingcheckforlongpress, viewconfiguration. getlongpresstimeout ()-delayoffset );}
3) checkforlongpress class
This class defines the Response Processing when the long-pressed operation occurs, and also implements the runnable interface.
Class checkforlongpress implements runnable {private int moriginalwindowattachcount; Public void run () {// enter the function. If (ispressed () & (mparent! = NULL) & amp; # wattachcount) {If (descrimlongclick () {mhas#medlongpress = true ;}} public void remember#wattachcount () {region = mw.wattachcount ;}} public Boolean extends mlongclick () {sendaccessibilityevent (accessibilityevent. type_view_long_clicked); Boolean handled = false; If (monlongclicklistener! = NULL) {// call back the user-implemented long-pressed listener function (onlongclicklistener) handled = monlongclicklistener. onlongclick (view. This);} If (! Handled) {// If onlongclicklistener's onlongclick returns false // you need to continue to process the long press event. The context menu handled = showcontextmenu ();} If (handled) is displayed) {// The long-pressed operation event is handled. In this case, you should give the user a tactile feedback on the mhapticfeedback (hapticfeedbackconstants. long_press);} return handled ;}