Author: Chen Yang Che-hung edge &
It originated from a colleague asked me: "how elegant double-click the listener," this behavior?
In fact, many similar events related, we can refer to the system source code, because sometimes completely into the system the ability to have some trouble, we could easily achieve a wanted feature.
The above example colleague asked:
How elegant double-click the listener?
I believe we more or less have some implementations, however, the system has provided us with GestureDetector
the class, if you are familiar with such realization, then the system will be able to choose for the same program, approval of the code will improve.
So today we have the opportunity to learn under:
GestureDetector
How about support gesture is detected?
Here is a small edge content analysis.
We create the class instance, the need to interfaces OnGestureListener
(used to monitor a variety of gestures) and implement it as a parameter passed into the constructor:
Explain the timing of each callback method (very easy to understand):
-
onDown
: Finger press; -
onShowPress
: After the finger is pressed, not raised within 100 milliseconds, is not moved; -
onSingleTapUp
: Press the finger is not moved, and lift (can be identified as clicking) within 500 milliseconds; -
onScroll
: Drag your finger; -
onLongPress
: Long press (press the finger, not raised within 500 milliseconds, not moved); -
onFling
: After dragging your finger quickly let go (inertial scrolling);
In addition OnGestureListener
, there are a OnDoubleTapListener
see be able to guess the name is used to monitor double-click the event:
explain:
-
onSingleTapConfirmed
: I have confirmed that this is a click event, want to trigger double-click must continue to quickly double-tap the screen (ie: after lift a finger, did not wait 300 milliseconds finger pressed again); -
onDoubleTap
: Double-click trigger event (after lifting the finger is pressed again within 300 ms (Note: It is triggered when pressed again, and so it was not raised before the trigger)) -
onDoubleTapEvent
: Trigger finger touch event after double click, includingACTION_DOWN
, ,ACTION_MOVE
(Note:ACTION_UP
After triggering long press, will not continue to receive theACTION_MOVE
event, because the finger press process, the process does not require movement of the finger movement, which is directly ignoreACTION_MOVE
the event. also, the callback method after this, before triggering long press event, if the new finger is pressed, it is no longer identified as a double-click, it will not continue to call back to this method, it replacedonScroll
). This approach with the aboveonDoubleTap
method difference is that,onDoubleTap
in the event of a double-click callback only once, and this method can callback times;
Well, it has a preliminary understanding later, take a look at it is how to detect these events.
1,onDown
Code for this class rarely, less than 800 lines (SDK28).
First look onDown method is when the callback (available at just the interface method CTRL + Click
method name corresponding to the location to locate specific call):
Super simple, listening to the ACTION_DOWN
events immediately pulled back.
2,onShowPress
Then take a look at onShowPress
methods (using just said method to locate):
It will GestureHandler
receive what
for the SHOW_PRESS
following message callbacks to see where the hair of the news:
emmm, also in receipt of ACTION_DOWN
the will to mHandler
(i.e. GestureHandler
sending) a message specifying a time, and this time is the pressing of the plus the time TAP_TIMEOUT
duration can be seen TAP_TIMEOUT
the value is based on ViewConfiguration
a getTapTimeout
method to obtain, and opening the one look:
Is 100 (ms), that is, when the finger is pressed, the delay if this task is not canceled within 100 milliseconds, then the onShowPress
method will callback.
3,onSingleTapUp & onScroll
OK, now take a look at onSingleTapUp
:
You can see that it is at ACTION_UP
the time the callback, the callback must meet three conditions, namely:
1.mIsDoubleTapping to false (ie, double-click the event is not triggered);
2.mInLongPress to false (ie long press event is not triggered);
3.mAlwaysInTapRegion为true;
mAlwaysInTapRegion
What time it is true
, what time is false
it:
There are three places assignment, namely:
1. ACTION_POINTER_DOWN
When (another finger press) is false
, that is to say, if only the first finger is pressed, there are 100 milliseconds new finger press, then when the lift will not trigger finger onSingleTapUp
;
2. ACTION_DOWN
when (only the first finger press) true
;
3. ACTION_MOVE
When, look else if
inside that if
, it is judged distance
(moving distance of the finger) is greater than slopSquare
(the minimum trigger distance moved), and if so, will the callback onScroll
method, and the mAlwaysInTapRegion
set false
, which indicates that, if the finger is pressed 100 within seconds, began to drag, then onSingleTapUp
the method is not callback;
You can also see when mAlwaysInTapRegion
is set false
after the next ACTION_MOVE
time comes, if there is no trigger double-click (ie, above mIsDoubleTapping为false
) and the horizontal or vertical movement of the finger distance is not 0, then, it would have been the callback onScroll
method.
Well, now onScroll
, also spoke, turn onLongPress
up.
4,onLongPress
Now onShowPress
is the same method by means of Handler
timing mechanism to achieve message, it is received LONG_PRESS
after the message, calls the dispatchLongPress
method, dispatchLongPress
the method will first mark mInLongPress
astrue
(Note: This will affect when it comes to the top of the onSingleTapUp
callback, because onSingleTapUp
callback condition is the need mInLongPress
to false
(ie long press does not trigger))
Then callback onLongPress
method.
So LONG_PRESS
the message when to send it?
Also at ACTION_DOWN
the time:
Before sending a message, it will first check if the monitor is turned on press events, as well as issuing press correction and did not perform the task once the cancellation.
Given time you can see down event time plus getLongPressTimeout
the length method returns the default is 500 (ms), that is, when the finger is pressed half a second, onLongPress
the method will be called back, of course, provided that this task has not been cancel.
There are several situations can cause long been canceled by the callback tasks:
Within 500ms new finger is pressed;
Within 500ms triggered onScroll
, namely finger movement over a specified distance;
Lift your finger within 500ms;
Within 500ms received the ACTION_CANCEL
event (which ACTION
is generally derived from the parent container privately creation);
Take a look onFling
:
5,onFling
We usually deal with inertial scrolling makes no difference, except that it will first determine whether the callback before sliding speed greater than the specified minimum speed, or not to carry out rolling rolling.
Well, finally we look at onSingleTapConfirmed
, onDoubleTap
, onDoubleTapEvent
respectively, is how to deal with:
onSingleTapConfirmed、onDoubleTap、onDoubleTapEvent
private class GestureHandler extends Handler {
......
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
......
case TAP:
if (mDoubleTapListener != null) {
if (!mStillDown) {
mDoubleTapListener.onSingleTapConfirmed(mCurrentDownEvent);
} else {
mDeferConfirmSingleTap = true;
}
}
break;
......
}
}
}
public boolean onTouchEvent(MotionEvent ev) {
......
boolean handled = false;
switch (action & MotionEvent.ACTION_MASK) {
......
case MotionEvent.ACTION_DOWN:
......
if (isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) {
mIsDoubleTapping = true;
handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
handled |= mDoubleTapListener.onDoubleTapEvent(ev);
} else {
mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
}
mStillDown = true;
......
break;
case MotionEvent.ACTION_MOVE:
if (mIsDoubleTapping) {
handled |= mDoubleTapListener.onDoubleTapEvent(ev);
}
......
break;
case MotionEvent.ACTION_UP:
mStillDown = false;
if (mIsDoubleTapping) {
handled |= mDoubleTapListener.onDoubleTapEvent(ev);
}
......
if (mIsDoubleTapping) {
......
} else if (mInLongPress) {
......
} else if (mAlwaysInTapRegion) {
handled = mListener.onSingleTapUp(ev);
if (mDeferConfirmSingleTap && mDoubleTapListener != null) {
mDoubleTapListener.onSingleTapConfirmed(ev);
}
}
......
break;
......
}
......
return handled;
}
First look at the onSingleTapConfirmed
method, it has called in two places, namely:
GestureHandler
Receive the TAP
message
Processing ACTION_UP
event
When the GestureHandler
received TAP
message it checks whether the finger has been lifted ( !mStillDown
), if already lifted, it would be called immediately, otherwise the mDeferConfirmSingleTap
mark true
to indicate onSingleTapConfirmed
the method should ACTION_UP
callback, can be seen in the process ACTION_UP
, if the finger not moved and did not press the trigger, it would determine mDeferConfirmSingleTap
whether true
, yes, it would callback onSingleTapConfirmed
method.
Then look at ACTION_DOWN
, it calls the isConsideredDoubleTap
method to determine whether the incident was identified by double-clicking, and if not, will be to GestureHandler
send a message latency (delay callback onSingleTapConfirmed
method)
If so, will the mIsDoubleTapping
mark true
, followed by the callback onDoubleTap
and onDoubleTapEvent
. It can be seen in ACTION_MOVE
and ACTION_UP
will also According mIsDoubleTapping
to determine whether to continue the callback onDoubleTapEvent
method.
Well, now look, whether it is how recognized as a double-click to see isConsideredDoubleTap
the method:
First, the judge mAlwaysInBiggerTapRegion
, if it is false
, then the representatives of the other actions ( ACTION_MOVE
, ) ACTION_CANCEL
interrupted detect double-click events, it is returned directly false
(ie, not identified by double-clicking) a.
Then determines the first and second press pressing time interval, it is asserted if more than 300 milliseconds is timed out, if less than 40 ms will be ignored (too fast).
Finally, many students may at first glance, do not see what kind of logic, a close look at a few times, you will know that this is actually the first time in the computing press and hold down the second coordinate distance, is calculated using two the distance between the point of formula (√ (x1 - x2) ² + (y1 - y2) ²).
At this point some students might ask:
Not even open square it? It is how the code is not it?
In fact, that slopSquare
(that is, double-click can be identified as the maximum interval) during initialization, it has been squaring up, so there is no need to open the square.
emmm, then the isConsideredDoubleTap
method last sentence means that, whether the coordinates of the touch event twice within a specified interval is the maximum interval range, and if so, is that it is the double-click.
Finally, attach my Android core technology learning syllabus, access to relevant content to play with my GitHub: https://github.com/Meng997998/AndroidJX
You take your time to invest in learning, it means that you can gain skills, have the opportunity to increase revenue.
Here to share my Android PDF Daquan learn to learn, learn this Android PDF Daquan really contain all aspects, and contains basic Java knowledge, the basis of Android, Android Advanced extension, and so on collection algorithm
Android-related learning content: concern I see personal introduction , or direct private letter I
My collection this study, can effectively help you grasp the knowledge points.
In short we are also here to help enhance learning advanced, but also saves you the time to learn online search data can also be shared with close friends studying together