Analysis of touch events, click events, and longclick events in android

For a View control on the screen, how does Android distinguish between onTouchEvent, onClick, or onLongClick event?

In Android, a user operation can be processed separately by different Views in order, and a UI operation that fully responds to the user is called consuming the event (consume). Then in what order does Android deliver the event? Under what circumstances is the event determined to be consumed?

      Understanding these issues is very important to write code that can correctly respond to UI operations, especially when different Views on the screen need to respond differently to this UI operation. A typical example is when the user is in A widget is placed on the desktop. When the user performs various operations on the widget, the desktop itself sometimes responds to the user's operation, and sometimes ignores it. Only by figuring out the mechanism of event triggering and delivery can it be possible to ensure that UI controls can still correctly respond to user operations in the case of very complex interface layouts.



1. onTouchEvent

     The three most commonly used events to be processed in onTouchEvent are: ACTION_DOWN, ACTION_MOVE, and ACTION_UP.

     These three events identify the most basic user touch screen operations, and the meaning is very clear. Although everyone uses them every day, please note that the ACTION_DOWN event is the starting event, and its importance is more than ACTION_MOVE and ACTION_UP. If ACTION_MOVE or ACTION_UP occurs, then ACTION_DOWN must have occurred.

     From the source code of Android, we can see some interaction mechanisms based on this understanding of different importance, which are also clearly mentioned in the SDK. For example, in the onInterceptTouchEvent method of ViewGroup, if true is returned in the ACTION_DOWN event, then Subsequent events will be sent directly to onTouchEvent instead of continuing to onInterceptTouchEvent.



2. onClick, onLongClick and onTouchEvent

     I have read a post that mentioned that if onTouchEvent is handled in the View, then onClick will not need to be handled, because Android will only trigger one of the methods. This understanding is not quite correct. For a certain view, the user has completed a touch operation. Obviously, the signal obtained from the sensor is the two operations of pressing and lifting the finger. We can understand it as a Click, or it can be understood as There is an ACTION_DOWN and ACTION_UP, so how does Android understand and handle it?

     In Android, the triggering of onClick and onLongClick is related to ACTION_DOWN and ACTION_UP. In terms of timing, if we overwrite onClick, onLongClick and onTouchEvent in a View at the same time, onTouchEvent is the first to capture ACTION_DOWN and ACTION_UP events. Second, it is possible to trigger onClick or onLongClick. The main logic is implemented in the onTouchEvent method in View.java:
case MotionEvent.ACTION_DOWN:

    mPrivateFlags |= PRESSED;

    refreshDrawableState();

    if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {

         postCheckForLongClick();

    }

    break;

case MotionEvent.ACTION_UP:

    if ((mPrivateFlags & PRESSED) != 0) {

         boolean focusTaken = false;

         if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {

               focusTaken = requestFocus();

         }

 

    if (!mHasPerformedLongPress) {

       if (mPendingCheckForLongPress != null) {

             removeCallbacks(mPendingCheckForLongPress);

       }

       if (!focusTaken) {

              performClick();

       }

    }


    break;


It can be seen that the trigger of Click occurs after the system captures ACTION_UP and is executed by performClick(). The onClick() method of the previously registered listener will be called in performClick:
public boolean performClick() {


    if (mOnClickListener != null) {

        playSoundEffect(SoundEffectConstants.CLICK);

        mOnClickListener.onClick(this);

        return true;

    }

        return false;

}

 

The triggering of LongClick starts from ACTION_DOWN and is completed by the postCheckForLongClick() method:
private void postCheckForLongClick() {

     mHasPerformedLongPress = false;

     if (mPendingCheckForLongPress == null) {

         mPendingCheckForLongPress = new CheckForLongPress();

     }

     mPendingCheckForLongPress.rememberWindowAttachCount();

     postDelayed(mPendingCheckForLongPress, ViewConfiguration.getLongPressTimeout());

}

It can be seen that after the ACTION_DOWN event is captured, the system will start to trigger a postDelayed operation, the delay time is 500ms on Eclair2.1, and the execution of the CheckForLongPress thread will be triggered after 500ms:
class CheckForLongPress implements Runnable {


        public void run() {

            if (isPressed() && (mParent != null)

                    && mOriginalWindowAttachCount == mWindowAttachCount) {

                if (performLongClick()) {

                    mHasPerformedLongPress = true;

                }

            }

        }


}

If various conditions are met, performLongClick() is executed in CheckForLongPress, and onLongClick() will be called in this method:
public boolean performLongClick() {


      if (mOnLongClickListener != null) {

          handled = mOnLongClickListener.onLongClick(View.this);

      }


}

It can be seen from the implementation that the onClick() and onLongClick() methods are captured by the ACTION_DOWN and ACTION_UP events and finally determine whether to trigger according to various situations, that is to say, if we monitor or override onClick at the same time in an Activity or View (), onLongClick() and onTouchEvent() methods, it does not mean that only one of them will happen.



The following is a log of the basic timing when onClick is triggered:

04-05 05:57:47.123: DEBUG/TSActivity(209): onTouch ACTION_DOWN

04-05 05:57:47.263: DEBUG/TSActivity(209): onTouch ACTION_UP

04- 05 05:57:47.323: DEBUG/TSActivity(209):

It can be seen that onClick occurs in the order of ACTION_DOWN -> ACTION_UP -> onClick.



The following is a log of the basic timing when onLongClick is triggered:

04-05 06:00:04.133: DEBUG/TSActivity(248): onTouch ACTION_DOWN

04-05 06:00:04.642: DEBUG/TSActivity(248): onLongClick

04-05 06:00:05.083: DEBUG/TSActivity(248): onTouch ACTION_UP As

you can see, onLongClick will be triggered after a certain period of time, and then ACTION_UP will occur when the hand is raised.



3. Can onClick and onLongClick happen at the same time?

     To figure out this problem, you only need to understand the concept of Android's so-called consumption of event processing. A user's operation will be passed to different View controls and different listening methods of the same control. Any one receives and processes the If the method of the sub-event returns true after processing, then the event is completely processed, and other View or listening methods will not have the opportunity to process the event.

     The occurrence of onLongClick is completed by a separate thread, and before ACTION_UP, and onClick occurs after ACTION_UP, so the same user touch operation may occur both onLongClick and onClick. Isn't that incredible? Therefore, it is very important to indicate to the system in time that "I have completely processed (consumed) this user's operation". For example, if we return true at the end of the onLongClick() method, then the onClick event has no chance to be fired.



The following Log is the basic timing of a touch operation when the onLongClick() method returns false:

04-05 06:00:53.023: DEBUG/TSActivity(277): onTouch ACTION_DOWN

04-05 06:00:53.533: DEBUG/TSActivity(277): onLongClick

04-05 06:00:55.603: DEBUG/TSActivity(277): onTouch ACTION_UP

04-05 06:00:55.663: DEBUG/TSActivity(277): onClick

As you can see, the onClick() method is still triggered after ACTION_UP.


Original address: http://blog.csdn.net/xixinyan/article/details/6759632

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326627407&siteId=291194637