In the previous article, we analyzed the source code of View. onTouchEvent and found the processing principle of click and long-press events. But what if the custom control requires other gestures? If you need to determine a rolling event, the code you learned earlier cannot help, currently, you can also determine by yourself based on ACTOIN and the current Touch Location (if you want to customize rolling events, you can refer to the source code of ListView). However, the Android system provides a tool class to support these gestures.
The following is only a demonstration of how to use it. It does not list all supported gestures. For details, see the official document SimpleOnGestureListener. You can also read the source code to learn how to judge various gestures.
I,
Ii. Code
Custom Controls in Android usually involve Touch gestures. You need to determine the user's click, slide, Fling, and press statuses, currently, you can use the MotionEvent callback parameter in onTouchEvent. However, you can also use the helper class SimpleOnGestureListener provided by the Android system. The following are inherited from this class, the main purpose is to observe the functions of each callback.
If you want to know how multiple systems determine the source code of these gestures, you can also see the ListView. The source code of Gallery is how to determine the Tap, Scroll, and Fling gestures in AbsListView, the latter is used in the same way as this article. You can also view its source code to learn more about the usage of the current helper class.
Private class DefaultGestureListener extends SimpleOnGestureListener {// triggered when Touch down @ Overridepublic boolean onDown (MotionEvent e) {updateLog (onDown); return super. onDown (e);} // triggered @ Overridepublic void onShowPress (MotionEvent e) {updateLog (onShowPress) after Touch down for a certain period of time (115 ms );} @ Overridepublic boolean onSingleTapUp (MotionEvent e) {updateLog (onSingleTapUp); return super. onSingleTapUp (e);} // @ Overridepublic boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {updateLog (onScroll); return. onScroll (e1, e2, distanceX, distanceY);} // sliding distance. @ Overridepublic boolean onFling (MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) is triggered during up) {updateLog (onFling); return super. onFling (e1, e2, velocityX, velocityY);} // triggered after long-pressed (after Touch down for a certain period of time (500 ms) @ Overridepublic void onLongPress (MotionEvent e) {updateLog (onLongPress );}}
Create and trigger gestures
@ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); mOutput = (TextView) findViewById (R. id. output); output (); mGestureDetector = new GestureDetector (this, new DefaultGestureListener () ;}@ Overridepublic boolean onTouchEvent (MotionEvent event) {// clear the previous record if (event. getAction () = MotionEvent. ACTION_DOWN) {mRecordMap. clear ();} return mGestureDetector. onTouchEvent (event );}
Complete code
Package loveworld. gesturedetector; import java. util. linkedHashMap; import java. util. map; import android. app. activity; import android. OS. bundle; import android. text. textUtils; import android. util. log; import android. view. gestureDetector; import android. view. gestureDetector. simpleOnGestureListener; import android. view. motionEvent; import android. widget. textView;/*** Gesture Recognition *** step ** 1. inherited from SimpleOnGestureListener to create a subclass * 2. overwrite the corresponding methods, including long-pressed, sliding, and so on ** 3. create a GestureDetector in the Activity and pass in the Custom subclass instance mGestureDetector * 4. activity overwrites onTouchEvent and returns mGestureDetector. onTouchEvent (event ); **/public class GestureDetectorDemoActivity extends Activity {// ========================== ========================================/// Constants // ======== ========================================================== ======================= ==============================================================/// Fields // ========================================================== =========================== private TextView mOutput; private GestureDetector mGestureDetector; private LinkedHashMap
MRecordMap = new LinkedHashMap
(); // ================================================ ====================================/// Constructors // ======================== ========================================================== ================================================ ========================================/// Public Methods // ========================================================== ======================================================== ===================================== // Methods for/from SuperClass/ interfaces // ================== ========================================================== =======@ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); mOutput = (TextView) findViewById (R. id. output); output (); mGestureDetector = new GestureDetector (this, new DefaultGestureListener () ;}@ Overridepublic boolean onTouchEvent (MotionEvent event) {// clear the previous record if (event. getAction () = MotionEvent. ACTION_DOWN) {mRecordMap. clear ();} return mGestureDetector. onTouchEvent (event );} // ================================================ ====================================/// Private Methods // ==================== ========================================================== ===== private void updateLog (String name) {if (TextUtils. isEmpty (name) {return;} if (mRecordMap = null) {Log. e (Test, mRecordMap = null);} // The new boolean containsKey does not exist. = MRecordMap. containsKey (name); if (! ContainsKey) {mRecordMap. put (name, 0);} // retrieves the int oldCount = mRecordMap record. get (name); int count = oldCount + 1; // update record mRecordMap. put (name, count); // concatenate StringBuilder stringBuilder = new StringBuilder (); for (Map. entry
Entry: mRecordMap. entrySet () {String key = entry. getKey (); Integer value = entry. getValue (); stringBuilder. append (execution method: + key); stringBuilder. append (, execution times: + value); stringBuilder. append ();} output (stringBuilder. toString ();} private void output (String output) {mOutput. setText (sliding fingers on the screen: + output );} // ================================================ ======================================/inner and Anonymous Classes // ================ ========================================================== ======== private class DefaultGestureListener extends SimpleOnGestureListener {// @ Overridepublic boolean onDown (MotionEvent e) triggered when the Touch is down) {updateLog (onDown); return super. onDown (e);} // triggered @ Overridepublic void onShowPress (MotionEvent e) {updateLog (onShowPress) after Touch down for a certain period of time (115 ms );} @ Overridepublic boolean onSingleTapUp (MotionEvent e) {updateLog (onSingleTapUp); return super. onSingleTapUp (e);} // @ Overridepublic boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {updateLog (onScroll); return. onScroll (e1, e2, distanceX, distanceY);} // sliding distance. @ Overridepublic boolean onFling (MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) is triggered during up) {updateLog (onFling); return super. onFling (e1, e2, velocityX, velocityY);} // triggered after long-pressed (after Touch down for a certain period of time (500 ms) @ Overridepublic void onLongPress (MotionEvent e) {updateLog (onLongPress );}}}
Layout. xml
3. Another method of use
The custom class inherits from SimpleOnGestureListener and implements OnTouchListener. When creating a custom view, this custom class is created and setOnTouchListener (the current custom class object ).
What is the call sequence between the custom class and the onTouchEvent of the current custom view?
Relationship between setOnTouchListener and onTouchEvent override method-setOnTouchListener is called in the dispatchTouchEvent of the current view
4. Possible Problems
If onScroll and onFling are not executed, You can overwrite onDown and return true.
Completely rewrite this article
Problems with adding
Organized into the Android event series on February 4
I,
Ii. Code
Custom Controls in Android usually involve Touch gestures. You need to determine the user's click, slide, Fling, and press statuses, currently, you can use the MotionEvent callback parameter in onTouchEvent. However, you can also use the helper class SimpleOnGestureListener provided by the Android system. The following are inherited from this class, the main purpose is to observe the functions of each callback.
If you want to know how multiple systems determine the source code of these gestures, you can also see the ListView. The source code of Gallery is how to determine the Tap, Scroll, and Fling gestures in AbsListView, the latter is used in the same way as this article. You can also view its source code to learn more about the usage of the current helper class.
Private class DefaultGestureListener extends SimpleOnGestureListener {// triggered when Touch down @ Overridepublic boolean onDown (MotionEvent e) {updateLog (onDown); return super. onDown (e);} // triggered @ Overridepublic void onShowPress (MotionEvent e) {updateLog (onShowPress) after Touch down for a certain period of time (115 ms );} @ Overridepublic boolean onSingleTapUp (MotionEvent e) {updateLog (onSingleTapUp); return super. onSingleTapUp (e);} // @ Overridepublic boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {updateLog (onScroll); return. onScroll (e1, e2, distanceX, distanceY);} // sliding distance. @ Overridepublic boolean onFling (MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) is triggered during up) {updateLog (onFling); return super. onFling (e1, e2, velocityX, velocityY);} // triggered after long-pressed (after Touch down for a certain period of time (500 ms) @ Overridepublic void onLongPress (MotionEvent e) {updateLog (onLongPress );}}
Create and trigger gestures
@ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); mOutput = (TextView) findViewById (R. id. output); output (); mGestureDetector = new GestureDetector (this, new DefaultGestureListener () ;}@ Overridepublic boolean onTouchEvent (MotionEvent event) {// clear the previous record if (event. getAction () = MotionEvent. ACTION_DOWN) {mRecordMap. clear ();} return mGestureDetector. onTouchEvent (event );}
Complete code
Package loveworld. gesturedetector; import java. util. linkedHashMap; import java. util. map; import android. app. activity; import android. OS. bundle; import android. text. textUtils; import android. util. log; import android. view. gestureDetector; import android. view. gestureDetector. simpleOnGestureListener; import android. view. motionEvent; import android. widget. textView;/*** Gesture Recognition *** step ** 1. inherited from SimpleOnGestureListener to create a subclass * 2. overwrite the corresponding methods, including long-pressed, sliding, and so on ** 3. create a GestureDetector in the Activity and pass in the Custom subclass instance mGestureDetector * 4. activity overwrites onTouchEvent and returns mGestureDetector. onTouchEvent (event ); **/public class GestureDetectorDemoActivity extends Activity {// ========================== ========================================/// Constants // ======== ========================================================== ======================= ==============================================================/// Fields // ========================================================== =========================== private TextView mOutput; private GestureDetector mGestureDetector; private LinkedHashMap
MRecordMap = new LinkedHashMap
(); // ================================================ ====================================/// Constructors // ======================== ========================================================== ================================================ ========================================/// Public Methods // ========================================================== ======================================================== ===================================== // Methods for/from SuperClass/ interfaces // ================== ========================================================== =======@ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); mOutput = (TextView) findViewById (R. id. output); output (); mGestureDetector = new GestureDetector (this, new DefaultGestureListener () ;}@ Overridepublic boolean onTouchEvent (MotionEvent event) {// clear the previous record if (event. getAction () = MotionEvent. ACTION_DOWN) {mRecordMap. clear ();} return mGestureDetector. onTouchEvent (event );} // ================================================ ====================================/// Private Methods // ==================== ========================================================== ===== private void updateLog (String name) {if (TextUtils. isEmpty (name) {return;} if (mRecordMap = null) {Log. e (Test, mRecordMap = null);} // The new boolean containsKey does not exist. = MRecordMap. containsKey (name); if (! ContainsKey) {mRecordMap. put (name, 0);} // retrieves the int oldCount = mRecordMap record. get (name); int count = oldCount + 1; // update record mRecordMap. put (name, count); // concatenate StringBuilder stringBuilder = new StringBuilder (); for (Map. entry
Entry: mRecordMap. entrySet () {String key = entry. getKey (); Integer value = entry. getValue (); stringBuilder. append (execution method: + key); stringBuilder. append (, execution times: + value); stringBuilder. append ();} output (stringBuilder. toString ();} private void output (String output) {mOutput. setText (sliding fingers on the screen: + output );} // ================================================ ======================================/inner and Anonymous Classes // ================ ========================================================== ======== private class DefaultGestureListener extends SimpleOnGestureListener {// @ Overridepublic boolean onDown (MotionEvent e) triggered when the Touch is down) {updateLog (onDown); return super. onDown (e);} // triggered @ Overridepublic void onShowPress (MotionEvent e) {updateLog (onShowPress) after Touch down for a certain period of time (115 ms );} @ Overridepublic boolean onSingleTapUp (MotionEvent e) {updateLog (onSingleTapUp); return super. onSingleTapUp (e);} // @ Overridepublic boolean onScroll (MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {updateLog (onScroll); return. onScroll (e1, e2, distanceX, distanceY);} // sliding distance. @ Overridepublic boolean onFling (MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) is triggered during up) {updateLog (onFling); return super. onFling (e1, e2, velocityX, velocityY);} // triggered after long-pressed (after Touch down for a certain period of time (500 ms) @ Overridepublic void onLongPress (MotionEvent e) {updateLog (onLongPress );}}}
Layout. xml
3. Another method of use
The custom class inherits from SimpleOnGestureListener and implements OnTouchListener. When creating a custom view, this custom class is created and setOnTouchListener (the current custom class object ).
What is the call sequence between the custom class and the onTouchEvent of the current custom view?
Relationship between setOnTouchListener and onTouchEvent override method-setOnTouchListener is called in the dispatchTouchEvent of the current view
4. Possible Problems
If onScroll and onFling are not executed, You can overwrite onDown and return true.
Completely rewrite this article
Problems with adding
Added to the event Learning Series on February 4