-
Notifications
You must be signed in to change notification settings - Fork 6.3k
Gestures and Touch Events
Gesture recognition and handling touch events is an important part of developing user interactions. Handling standard events such as clicks, long clicks, key presses, etc are very basic and handled in other guides. This guide is focused on handling other more specialized gestures such as:
- Swiping in a direction
- Double tapping for zooming
- Pinch to zoom in or out
- Dragging and dropping
- Handling a shake action
You can see a visual guide of common gestures on the gestures design patterns guide.
Gestures are typically used for more involved user interactions within an application. Let's take a look at how to implement common gestures.
You can enable double tap events for any view within your activity using the OnDoubleTapListener. First, copy the code for OnDoubleTapListener
into your application and then you can apply the listener with:
myView.setOnTouchListener(new OnDoubleTapListener(this) {
@Override
public void onDoubleTap(MotionEvent e) {
Toast.makeText(MainActivity.this, "Double Tap", Toast.LENGTH_SHORT).show();
}
});
Now that view will be able to respond to a double tap event and you can handle the event accordingly.
Detecting finger swipes in a particular direction is best done using the built-in [onFling](http://developer.android.com/reference/android/view/GestureDetector.OnGestureListener.html#onFling\(android.view.MotionEvent, android.view.MotionEvent, float, float)) event in the GestureDetector.OnGestureListener
.
A helper class that makes handling swipes as easy as possible can be found in the OnSwipeTouchListener class. Copy the OnSwipeTouchListener
class to your own application and then you can use the listener to manage the swipe events with:
myView.setOnTouchListener(new OnSwipeTouchListener(this) {
@Override
public void onSwipeDown() {
Toast.makeText(MainActivity.this, "Down", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeLeft() {
Toast.makeText(MainActivity.this, "Left", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeUp() {
Toast.makeText(MainActivity.this, "Up", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipeRight() {
Toast.makeText(MainActivity.this, "Right", Toast.LENGTH_SHORT).show();
}
});
With that code in place, swipe gestures should be easily manageable.
If you are interested in having a ListView that recognizes swipe gestures for each item, consider using the popular third-party library android-swipelistview which is a ListView replacement that supports swipe-eable items. Once setup, you can configure a layout that will appear when the item is swiped.
Check out the swipelistview project for more details but the general usage looks like:
<com.fortysevendeg.swipelistview.SwipeListView
xmlns:swipe="http://schemas.android.com/apk/res-auto"
android:id="@+id/example_lv_list"
android:listSelector="#00000000"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
swipe:swipeFrontView="@+id/front"
swipe:swipeBackView="@+id/back"
swipe:swipeActionLeft="reveal"
swipe:swipeActionRight="dismiss"
swipe:swipeMode="both"
swipe:swipeCloseAllItemsWhenMoveList="true"
/>
and then define the individual list item layout with:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:id="@+id/back"
android:tag="back"
style="@style/ListBackContent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/example_row_b_action_1"
style="@style/ListButtonAction"
android:text="@string/open"/>
</LinearLayout>
<RelativeLayout
android:orientation="vertical"
android:id="@+id/front"
android:tag="front"
style="@style/ListFrontContent">
<ImageView
style="@style/ListImage"
android:id="@+id/example_row_iv_image"/>
</RelativeLayout>
</FrameLayout>
Now front
will be displayed by default and if I swipe left on an item, then the back
will be displayed for that item. This simplifies swipes for the common case of menus for a ListView.
Supporting Pinch to Zoom in and out is fairly straightforward thanks to the ScaleGestureDetector class. Easiest way to manage pinch events is to subclass a view and manage the pinch event from within:
public class ScaleableTextView extends TextView
implements OnTouchListener, OnScaleGestureListener {
ScaleGestureDetector mScaleDetector =
new ScaleGestureDetector(getContext(), this);
public ScaleableTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
// Code for scale here
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
// Code for scale begin here
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
// Code for scale end here
}
@Override
public boolean onTouch(View v, MotionEvent event) {
if (mScaleDetector.onTouchEvent(event))
return true;
return super.onTouchEvent(event);
}
}
Using the ScaleGestureDetector
makes managing this fairly straightforward.
One of the most common use cases for a pinch or pannable view is for an ImageView that displays a Photo which can be zoomed or panned around on screen similar to the Facebook client. To achieve the zooming image view, rather than developing this yourself, be sure to check out the PhotoView third-party library. Using the PhotoView just requires the XML:
<uk.co.senab.photoview.PhotoView
android:id="@+id/iv_photo"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
and then in the Java:
// Any implementation of ImageView can be used!
mImageView = (ImageView) findViewById(R.id.iv_photo);
// Set the image bitmap
mImageView.setImageDrawable(someBitmap);
// Setup view attacher
PhotoViewAttacher mAttacher = new PhotoViewAttacher(mImageView);
Check out the PhotoView readme and sample for more details.
Dragging and dropping views is not particularly difficult to do thanks to the OnDragListener built in since API 11. Unfortunately, to support gingerbread managing drag and drop becomes much more manual as you have to implement it using the onTouch
handlers. With API 11 and above, you simply implement the onDrag
event.
myView.setOnDragListener(new OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_STARTED:
// Signals the start of a drag and drop operation.
// Code for that event here
break;
case DragEvent.ACTION_DRAG_ENTERED:
// Signals to a View that the drag point has
// entered the bounding box of the View. Code for that event here
break;
case DragEvent.ACTION_DRAG_EXITED:
// Signals that the user has moved the drag shadow
// outside the bounding box of the View. Code for that event here
break;
case DragEvent.ACTION_DROP:
// Signals to a View that the user has released the drag shadow,
// and the drag point is within the bounding box of the View. Code for that event here
break;
case DragEvent.ACTION_DRAG_ENDED:
// Signals to a View that the drag and drop operation has concluded.
// Code for that event here
default:
break;
}
return true;
}
});
Read the official dragging and scaling guide for a comprehensive overview. Check out the dragging tutorial on Vogella for a detailed look at handling dragging and dropping.
Detecting when the device is shaked requires using the sensor data to determine movement. We can whip up a special listener which manages this shake recognition for us. First, copy the ShakeListener into your project. Now, we can implement ShakeListener.Callback
in any activity:
public class MainActivity extends Activity
implements ShakeListener.Callback {
@Override
public void shakingStarted() {
// Code on started here
}
@Override
public void shakingStopped() {
// Code on stopped here
}
}
Now we just have to implement the expected behavior for the shaking event in the two methods from the callback.
Additional multi-touch events such as "rotation" of fingers, finger movement events, etc you can check out the multitouch-gesture-detectors third-party library. Read the documentation for more details about how to handle multi-touch gestures. Also, for a more generic approach, read the official multitouch guide.
- android-swipelistview - A List View with swipeable cells
- gesticulate - Android swipe detection made simple
- android-gesture-detectors - small framework for gesture detection
- PhotoView - ImageView for Android that supports zooming, by various touch gestures.
- http://developer.android.com/training/gestures/index.html
- http://developer.android.com/design/patterns/gestures.html
- http://developer.android.com/training/gestures/detector.html
- http://developer.android.com/training/gestures/multi.html
- http://mobile.tutsplus.com/tutorials/android/android-gesture/
- http://www.codeproject.com/Articles/319401/Simple-Gestures-on-Android
- http://www.vogella.com/articles/AndroidTouch/article.html
- http://androidrises.blogspot.com/2012/10/draw-line-on-finger-touch.html
- http://mrbool.com/how-to-work-with-swipe-gestures-in-android/28088
- http://www.codeproject.com/Articles/319401/Simple-Gestures-on-Android
Created by CodePath with much help from the community. Contributed content licensed under cc-wiki with attribution required. You are free to remix and reuse, as long as you attribute and use a similar license.
Finding these guides helpful?
We need help from the broader community to improve these guides, add new topics and keep the topics up-to-date. See our contribution guidelines here and our topic issues list for great ways to help out.
Check these same guides through our standalone viewer for a better browsing experience and an improved search. Follow us on twitter @codepath for access to more useful Android development resources.