在应用中,监听到点击事件会调用到
onTouch(MotionEvent e) 方法,
怎么来识别是什么点击操作呢,常用的事件主要是点击,长按,滑动等,
我们可以写方法来进行识别判断,
写一个判断方法,如果是点击,就调用相应的处理,长按,就调用长按的处理方法,
可以设计一个观察者模式listener来进行实现,
Google也是这么想的,Android中提供了GestureDetector 来进行常规手势的识别处理,
GestureDetector的用法可以参考
https://www.cnblogs.com/ldq2016/p/7000300.html
https://www.cnblogs.com/yuanhao-1999/p/11081980.html
这里我们来看看GestureDetector的设计,
为了方便进行相应的操作,定义了listener接口,
40public class GestureDetector {
41 /**
42 * The listener that is used to notify when gestures occur.
43 * If you want to listen for all the different gestures then implement
44 * this interface. If you only want to listen for a subset it might
45 * be easier to extend {@link SimpleOnGestureListener}.
46 */
47 public interface OnGestureListener {
48
49 /**
50 * Notified when a tap occurs with the down {@link MotionEvent}
51 * that triggered it. This will be triggered immediately for
52 * every down event. All other events should be preceded by this.
53 *
54 * @param e The down motion event.
55 */
56 boolean onDown(MotionEvent e);
57
58 /**
59 * The user has performed a down {@link MotionEvent} and not performed
60 * a move or up yet. This event is commonly used to provide visual
61 * feedback to the user to let them know that their action has been
62 * recognized i.e. highlight an element.
63 *
64 * @param e The down motion event
65 */
66 void onShowPress(MotionEvent e);
67
68 /**
69 * Notified when a tap occurs with the up {@link MotionEvent}
70 * that triggered it.
71 *
72 * @param e The up motion event that completed the first tap
73 * @return true if the event is consumed, else false
74 */
75 boolean onSingleTapUp(MotionEvent e);
76
77 /**
78 * Notified when a scroll occurs with the initial on down {@link MotionEvent} and the
79 * current move {@link MotionEvent}. The distance in x and y is also supplied for
80 * convenience.
81 *
82 * @param e1 The first down motion event that started the scrolling.
83 * @param e2 The move motion event that triggered the current onScroll.
84 * @param distanceX The distance along the X axis that has been scrolled since the last
85 * call to onScroll. This is NOT the distance between {@code e1}
86 * and {@code e2}.
87 * @param distanceY The distance along the Y axis that has been scrolled since the last
88 * call to onScroll. This is NOT the distance between {@code e1}
89 * and {@code e2}.
90 * @return true if the event is consumed, else false
91 */
92 boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY);
93
94 /**
95 * Notified when a long press occurs with the initial on down {@link MotionEvent}
96 * that trigged it.
97 *
98 * @param e The initial on down motion event that started the longpress.
99 */
100 void onLongPress(MotionEvent e);
101
102 /**
103 * Notified of a fling event when it occurs with the initial on down {@link MotionEvent}
104 * and the matching up {@link MotionEvent}. The calculated velocity is supplied along
105 * the x and y axis in pixels per second.
106 *
107 * @param e1 The first down motion event that started the fling.
108 * @param e2 The move motion event that triggered the current onFling.
109 * @param velocityX The velocity of this fling measured in pixels per second
110 * along the x axis.
111 * @param velocityY The velocity of this fling measured in pixels per second
112 * along the y axis.
113 * @return true if the event is consumed, else false
114 */
115 boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY);
116 }
117
118 /**
119 * The listener that is used to notify when a double-tap or a confirmed
120 * single-tap occur.
121 */
122 public interface OnDoubleTapListener {
123 /**
124 * Notified when a single-tap occurs.
125 * <p>
126 * Unlike {@link OnGestureListener#onSingleTapUp(MotionEvent)}, this
127 * will only be called after the detector is confident that the user's
128 * first tap is not followed by a second tap leading to a double-tap
129 * gesture.
130 *
131 * @param e The down motion event of the single-tap.
132 * @return true if the event is consumed, else false
133 */
134 boolean onSingleTapConfirmed(MotionEvent e);
135
136 /**
137 * Notified when a double-tap occurs.
138 *
139 * @param e The down motion event of the first tap of the double-tap.
140 * @return true if the event is consumed, else false
141 */
142 boolean onDoubleTap(MotionEvent e);
143
144 /**
145 * Notified when an event within a double-tap gesture occurs, including
146 * the down, move, and up events.
147 *
148 * @param e The motion event that occurred during the double-tap gesture.
149 * @return true if the event is consumed, else false
150 */
151 boolean onDoubleTapEvent(MotionEvent e);
152 }
153
识别处理,
public boolean onTouchEvent(MotionEvent ev) {
…
556 case MotionEvent.ACTION_DOWN:
557 if (mDoubleTapListener != null) {
558 boolean hadTapMessage = mHandler.hasMessages(TAP);
559 if (hadTapMessage) mHandler.removeMessages(TAP);
560 if ((mCurrentDownEvent != null) && (mPreviousUpEvent != null)
561 && hadTapMessage
562 && isConsideredDoubleTap(mCurrentDownEvent, mPreviousUpEvent, ev)) {
563 // This is a second tap
564 mIsDoubleTapping = true;
565 // Give a callback with the first tap of the double-tap
566 handled |= mDoubleTapListener.onDoubleTap(mCurrentDownEvent);
567 // Give a callback with down event of the double-tap
568 handled |= mDoubleTapListener.onDoubleTapEvent(ev);
569 } else {
570 // This is a first tap
571 mHandler.sendEmptyMessageDelayed(TAP, DOUBLE_TAP_TIMEOUT);
572 }
识别出相应的手势后,通过handle机制的sendMessage来把事件抛出去,由UI主线程去处理,GestureDetector初始化的时候已经构造了handle对象
351 /**
352 * Creates a GestureDetector with the supplied listener.
353 * You may only use this constructor from a {@link android.os.Looper} thread.
354 * @see android.os.Handler#Handler()
355 *
356 * @param context the application's context
357 * @param listener the listener invoked for all the callbacks, this must
358 * not be null.
359 *
360 * @throws NullPointerException if {@code listener} is null.
361 */
362 public GestureDetector(Context context, OnGestureListener listener) {
363 this(context, listener, null);
364 }
365
366 /**
367 * Creates a GestureDetector with the supplied listener that runs deferred events on the
368 * thread associated with the supplied {@link android.os.Handler}.
369 * @see android.os.Handler#Handler()
370 *
371 * @param context the application's context
372 * @param listener the listener invoked for all the callbacks, this must
373 * not be null.
374 * @param handler the handler to use for running deferred listener events.
375 *
376 * @throws NullPointerException if {@code listener} is null.
377 */
378 public GestureDetector(Context context, OnGestureListener listener, Handler handler) {
379 if (handler != null) {
380 mHandler = new GestureHandler(handler);
381 } else {
382 mHandler = new GestureHandler();
383 }
384 mListener = listener;
385 if (listener instanceof OnDoubleTapListener) {
386 setOnDoubleTapListener((OnDoubleTapListener) listener);
387 }
388 if (listener instanceof OnContextClickListener) {
389 setContextClickListener((OnContextClickListener) listener);
390 }
391 init(context);
392 }
GestureDetector的设计还是非常经典的观察者模式调用,同时里面用到了handle消息分发。
这个设计方法可以给我们启发来进行类似的功能设计。