|  | page.title=Detecting Common Gestures | 
|  | parent.title=Using Touch Gestures | 
|  | parent.link=index.html | 
|  |  | 
|  | trainingnavtop=true | 
|  | next.title=Tracking Movement | 
|  | next.link=movement.html | 
|  |  | 
|  | @jd:body | 
|  |  | 
|  | <div id="tb-wrapper"> | 
|  | <div id="tb"> | 
|  |  | 
|  | <!-- table of contents --> | 
|  | <h2>This lesson teaches you to</h2> | 
|  | <ol> | 
|  | <li><a href="#data">Gather Data</a></li> | 
|  | <li><a href="#detect">Detect Gestures</a></li> | 
|  | </ol> | 
|  |  | 
|  | <!-- other docs (NOT javadocs) --> | 
|  | <h2>You should also read</h2> | 
|  |  | 
|  | <ul> | 
|  | <li><a href="http://developer.android.com/guide/topics/ui/ui-events.html">Input Events</a> API Guide | 
|  | </li> | 
|  | <li><a href="{@docRoot}guide/topics/sensors/sensors_overview.html">Sensors Overview</a></li> | 
|  | <li><a href="{@docRoot}training/custom-views/making-interactive.html">Making the View Interactive</a> </li> | 
|  | <li>Design Guide for <a href="{@docRoot}design/patterns/gestures.html">Gestures</a></li> | 
|  | <li>Design Guide for <a href="{@docRoot}design/style/touch-feedback.html">Touch Feedback</a></li> | 
|  | </ul> | 
|  |  | 
|  | <h2>Try it out</h2> | 
|  |  | 
|  | <div class="download-box"> | 
|  | <a href="{@docRoot}shareables/training/InteractiveChart.zip" | 
|  | class="button">Download the sample</a> | 
|  | <p class="filename">InteractiveChart.zip</p> | 
|  | </div> | 
|  |  | 
|  | </div> | 
|  | </div> | 
|  |  | 
|  | <p>A "touch gesture" occurs when a user places one or more fingers on the touch | 
|  | screen, and your application interprets | 
|  | that pattern of touches as a particular gesture. There are correspondingly two | 
|  | phases to gesture detection:</p> | 
|  |  | 
|  | <ol> | 
|  | <li>Gathering data about touch events.</li> | 
|  |  | 
|  | <li>Interpreting the data to see if it meets the criteria for any of the | 
|  | gestures your app supports. </li> | 
|  |  | 
|  | </ol> | 
|  |  | 
|  | <h4>Support Library Classes</h4> | 
|  |  | 
|  | <p>The examples in this lesson use the {@link android.support.v4.view.GestureDetectorCompat} | 
|  | and {@link android.support.v4.view.MotionEventCompat} classes. These classes are in the | 
|  | <a href="{@docRoot}tools/support-library/index.html">Support Library</a>. You should use | 
|  | Support Library classes where possible to provide compatibility with devices | 
|  | running Android 1.6 and higher. Note that {@link android.support.v4.view.MotionEventCompat} is <em>not</em> a | 
|  | replacement for the {@link android.view.MotionEvent} class. Rather, it provides static utility | 
|  | methods to which you pass your {@link android.view.MotionEvent} object in order to receive | 
|  | the desired action associated with that event.</p> | 
|  |  | 
|  | <h2 id="data">Gather Data</h2> | 
|  |  | 
|  | <p>When a user places one or more fingers on the screen, this  triggers the | 
|  | callback {@link android.view.View#onTouchEvent onTouchEvent()} | 
|  | on the View that received the touch events. | 
|  | For each sequence of touch events (position, pressure, size, addition of another finger, etc.) | 
|  | that is ultimately identified as a gesture, | 
|  | {@link android.view.View#onTouchEvent onTouchEvent()} is fired several times.</p> | 
|  |  | 
|  | <p>The gesture starts when the user first touches the screen, continues as the system tracks | 
|  | the position of the user's finger(s), and ends by capturing the final event of | 
|  | the user's fingers leaving the screen. Throughout this interaction, | 
|  | the {@link android.view.MotionEvent} delivered to {@link android.view.View#onTouchEvent onTouchEvent()} | 
|  | provides the details of every interaction. Your app can use the data provided by the {@link android.view.MotionEvent} | 
|  | to determine if a gesture it cares | 
|  | about happened.</p> | 
|  |  | 
|  | <h3>Capturing touch events for an Activity or View</h3> | 
|  |  | 
|  | <p><p>To intercept touch events in an Activity or View, override | 
|  | the {@link android.view.View#onTouchEvent onTouchEvent()} callback.</p> | 
|  |  | 
|  | <p>The following snippet uses | 
|  | {@link android.support.v4.view.MotionEventCompat#getActionMasked getActionMasked()} | 
|  | to extract the action the user performed from the {@code event} parameter. This gives you the raw | 
|  | data you need to determine if a gesture you care about occurred:</p> | 
|  |  | 
|  | <pre> | 
|  | public class MainActivity extends Activity { | 
|  | ... | 
|  | // This example shows an Activity, but you would use the same approach if | 
|  | // you were subclassing a View. | 
|  | @Override | 
|  | public boolean onTouchEvent(MotionEvent event){ | 
|  |  | 
|  | int action = MotionEventCompat.getActionMasked(event); | 
|  |  | 
|  | switch(action) { | 
|  | case (MotionEvent.ACTION_DOWN) : | 
|  | Log.d(DEBUG_TAG,"Action was DOWN"); | 
|  | return true; | 
|  | case (MotionEvent.ACTION_MOVE) : | 
|  | Log.d(DEBUG_TAG,"Action was MOVE"); | 
|  | return true; | 
|  | case (MotionEvent.ACTION_UP) : | 
|  | Log.d(DEBUG_TAG,"Action was UP"); | 
|  | return true; | 
|  | case (MotionEvent.ACTION_CANCEL) : | 
|  | Log.d(DEBUG_TAG,"Action was CANCEL"); | 
|  | return true; | 
|  | case (MotionEvent.ACTION_OUTSIDE) : | 
|  | Log.d(DEBUG_TAG,"Movement occurred outside bounds " + | 
|  | "of current screen element"); | 
|  | return true; | 
|  | default : | 
|  | return super.onTouchEvent(event); | 
|  | } | 
|  | }</pre> | 
|  |  | 
|  | <p>You can then do your own processing on these events to determine if a | 
|  | gesture occurred. This is the kind of processing you would have to do for a | 
|  | custom gesture. However, if your app uses | 
|  | common gestures such as double tap, long press, fling, and so on, you can | 
|  | take advantage of the {@link | 
|  | android.view.GestureDetector} class. {@link | 
|  | android.view.GestureDetector} makes it easy for you to detect common | 
|  | gestures without processing the individual touch events yourself. This is | 
|  | discussed below in <a href="#detect">Detect Gestures</a>.</p> | 
|  |  | 
|  | <h3>Capturing touch events for a single view</h3> | 
|  |  | 
|  | <p>As an alternative to {@link android.view.View#onTouchEvent onTouchEvent()}, | 
|  | you can attach an {@link android.view.View.OnTouchListener} object to any {@link | 
|  | android.view.View} object using the {@link android.view.View#setOnTouchListener | 
|  | setOnTouchListener()} method. This makes it possible to to listen for touch | 
|  | events without subclassing an existing {@link android.view.View}. For | 
|  | example:</p> | 
|  |  | 
|  | <pre>View myView = findViewById(R.id.my_view); | 
|  | myView.setOnTouchListener(new OnTouchListener() { | 
|  | public boolean onTouch(View v, MotionEvent event) { | 
|  | // ... Respond to touch events | 
|  | return true; | 
|  | } | 
|  | });</pre> | 
|  |  | 
|  | <p>Beware of creating a listener that returns {@code false} for the | 
|  | {@link android.view.MotionEvent#ACTION_DOWN} event. If you do this, the listener will | 
|  | not be called for the subsequent {@link android.view.MotionEvent#ACTION_MOVE} | 
|  | and {@link android.view.MotionEvent#ACTION_UP} string of events. This is because | 
|  | {@link android.view.MotionEvent#ACTION_DOWN} is the starting point for all touch events.</p> | 
|  |  | 
|  | <p>If you are creating a custom View, you can override | 
|  | {@link android.view.View#onTouchEvent onTouchEvent()}, | 
|  | as described above.</p> | 
|  |  | 
|  | <h2 id="detect">Detect Gestures</h2> | 
|  |  | 
|  | <p>Android provides the {@link android.view.GestureDetector} class for detecting | 
|  | common gestures. Some of the gestures it supports include {@link | 
|  | android.view.GestureDetector.OnGestureListener#onDown onDown()}, {@link | 
|  | android.view.GestureDetector.OnGestureListener#onLongPress onLongPress()}, | 
|  | {@link android.view.GestureDetector.OnGestureListener#onFling onFling()}, and so | 
|  | on. You can use {@link android.view.GestureDetector} in conjunction with the | 
|  | {@link android.view.View#onTouchEvent onTouchEvent()} | 
|  | method described above.</p> | 
|  |  | 
|  |  | 
|  | <h3>Detecting All Supported Gestures</h3> | 
|  |  | 
|  | <p>When you instantiate a {@link android.support.v4.view.GestureDetectorCompat} | 
|  | object, one of the parameters it takes is a class that implements the | 
|  | {@link android.view.GestureDetector.OnGestureListener} interface. | 
|  | {@link android.view.GestureDetector.OnGestureListener} notifies users when | 
|  | a particular touch event has occurred. To make it possible for your | 
|  | {@link android.view.GestureDetector} object to receive events, you override | 
|  | the View or Activity's {@link android.view.View#onTouchEvent onTouchEvent()} method, | 
|  | and pass along all observed events to the detector instance.</p> | 
|  |  | 
|  |  | 
|  | <p>In the following snippet, a return value of {@code true} from the individual | 
|  | <code>on<em><TouchEvent></em></code> methods indicates that you | 
|  | have handled the touch event. A return value of {@code false} passes events down | 
|  | through the view stack until the touch has been successfully handled.</p> | 
|  |  | 
|  | <p>Run the following snippet to get a feel for how actions are triggered when | 
|  | you interact with the touch screen, and what the contents of the {@link | 
|  | android.view.MotionEvent} are for each touch event. You will realize how much | 
|  | data is being generated for even simple interactions.</p> | 
|  |  | 
|  | <pre>public class MainActivity extends Activity implements | 
|  | GestureDetector.OnGestureListener, | 
|  | GestureDetector.OnDoubleTapListener{ | 
|  |  | 
|  | private static final String DEBUG_TAG = "Gestures"; | 
|  | private GestureDetectorCompat mDetector; | 
|  |  | 
|  | // Called when the activity is first created. | 
|  | @Override | 
|  | public void onCreate(Bundle savedInstanceState) { | 
|  | super.onCreate(savedInstanceState); | 
|  | setContentView(R.layout.activity_main); | 
|  | // Instantiate the gesture detector with the | 
|  | // application context and an implementation of | 
|  | // GestureDetector.OnGestureListener | 
|  | mDetector = new GestureDetectorCompat(this,this); | 
|  | // Set the gesture detector as the double tap | 
|  | // listener. | 
|  | mDetector.setOnDoubleTapListener(this); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onTouchEvent(MotionEvent event){ | 
|  | this.mDetector.onTouchEvent(event); | 
|  | // Be sure to call the superclass implementation | 
|  | return super.onTouchEvent(event); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onDown(MotionEvent event) { | 
|  | Log.d(DEBUG_TAG,"onDown: " + event.toString()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onFling(MotionEvent event1, MotionEvent event2, | 
|  | float velocityX, float velocityY) { | 
|  | Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public void onLongPress(MotionEvent event) { | 
|  | Log.d(DEBUG_TAG, "onLongPress: " + event.toString()); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, | 
|  | float distanceY) { | 
|  | Log.d(DEBUG_TAG, "onScroll: " + e1.toString()+e2.toString()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public void onShowPress(MotionEvent event) { | 
|  | Log.d(DEBUG_TAG, "onShowPress: " + event.toString()); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onSingleTapUp(MotionEvent event) { | 
|  | Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onDoubleTap(MotionEvent event) { | 
|  | Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onDoubleTapEvent(MotionEvent event) { | 
|  | Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onSingleTapConfirmed(MotionEvent event) { | 
|  | Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString()); | 
|  | return true; | 
|  | } | 
|  | }</pre> | 
|  |  | 
|  | <h3>Detecting a Subset of Supported Gestures</h3> | 
|  |  | 
|  | <p>If you only want to process a few gestures, you can extend {@link | 
|  | android.view.GestureDetector.SimpleOnGestureListener} instead of implementing | 
|  | the {@link android.view.GestureDetector.OnGestureListener} interface. </p> | 
|  | <p> | 
|  | {@link | 
|  | android.view.GestureDetector.SimpleOnGestureListener} provides an implementation | 
|  | for all of the <code>on<em><TouchEvent></em></code> methods by returning {@code false} | 
|  | for all of them. Thus you can override only the methods you care about. | 
|  | For | 
|  | example, the snippet below creates a class that extends {@link | 
|  | android.view.GestureDetector.SimpleOnGestureListener} and overrides {@link | 
|  | android.view.GestureDetector.OnGestureListener#onFling onFling()} and {@link | 
|  | android.view.GestureDetector.OnGestureListener#onDown onDown()}.</p> | 
|  |  | 
|  | <p>Whether or not you use {@link android.view.GestureDetector.OnGestureListener}, | 
|  | it's best practice to implement an | 
|  | {@link android.view.GestureDetector.OnGestureListener#onDown onDown()} | 
|  | method that returns {@code true}. This is because all gestures begin with an | 
|  | {@link android.view.GestureDetector.OnGestureListener#onDown onDown()} message. If you return | 
|  | {@code false} from {@link android.view.GestureDetector.OnGestureListener#onDown onDown()}, | 
|  | as {@link android.view.GestureDetector.SimpleOnGestureListener} does by default, | 
|  | the system assumes that you want to ignore the rest of the gesture, and the other methods of | 
|  | {@link android.view.GestureDetector.OnGestureListener} never get called. | 
|  | This has the potential to cause unexpected problems in your app. | 
|  | The only time you should return {@code false} from | 
|  | {@link android.view.GestureDetector.OnGestureListener#onDown onDown()} | 
|  | is if you truly want to ignore an entire gesture. </p> | 
|  |  | 
|  | <pre>public class MainActivity extends Activity { | 
|  |  | 
|  | private GestureDetectorCompat mDetector; | 
|  |  | 
|  | @Override | 
|  | public void onCreate(Bundle savedInstanceState) { | 
|  | super.onCreate(savedInstanceState); | 
|  | setContentView(R.layout.activity_main); | 
|  | mDetector = new GestureDetectorCompat(this, new MyGestureListener()); | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onTouchEvent(MotionEvent event){ | 
|  | this.mDetector.onTouchEvent(event); | 
|  | return super.onTouchEvent(event); | 
|  | } | 
|  |  | 
|  | class MyGestureListener extends GestureDetector.SimpleOnGestureListener { | 
|  | private static final String DEBUG_TAG = "Gestures"; | 
|  |  | 
|  | @Override | 
|  | public boolean onDown(MotionEvent event) { | 
|  | Log.d(DEBUG_TAG,"onDown: " + event.toString()); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | @Override | 
|  | public boolean onFling(MotionEvent event1, MotionEvent event2, | 
|  | float velocityX, float velocityY) { | 
|  | Log.d(DEBUG_TAG, "onFling: " + event1.toString()+event2.toString()); | 
|  | return true; | 
|  | } | 
|  | } | 
|  | } | 
|  | </pre> | 
|  |  | 
|  |  |