Android detect swipe events

If you are an Android developer, I guess this must have been one of the problems you have encountered. You  needed to detect swipe events on views so that you can do something on either of the direction swipe. For instance, do task 1 if the user swipes from left to right or vice versa.

Worry no more as by the end of this post, you will be able to bind to swipe events without writing any single line of code to handle the detection.

To simplify swipe detection, I created a simple class which you only call statically with the view to bind events to and listeners which are triggered when any of the swipe event is detected. With this class, you can create listeners for all the swipe events – TOP, RIGHT, BOTTOM, LEFT – or only create listener for only one swipe direction. E.g. only detect swipe left.

How to use the library

1: Download the class from Github Gist and paste it in your project as a java class. OR

2: Copy and paste into a new file in your project

/**
 * Created by Mutinda Boniface on 7/5/2015.
 */
public class SwipeEvents implements View.OnTouchListener {
    private SwipeCallback swipeCallback;
    private SwipeSingleCallback swipeSingleCallback;
    private SwipeDirection detectSwipeDirection;

    float x1, x2, y1, y2;
    View view;

    private static SwipeEvents newInstance(){
        return new SwipeEvents();
    }

    public static void detect( View view, SwipeCallback swipeCallback  ){
        SwipeEvents evt = SwipeEvents.newInstance();
        evt.swipeCallback = swipeCallback;
        evt.view = view;
        evt.detect();
    }

    public static void detectTop( View view, SwipeSingleCallback swipeSingleCallback){
        SwipeEvents evt = SwipeEvents.newInstance();
        evt.swipeSingleCallback = swipeSingleCallback;
        evt.view = view;
        evt.detectSingle(SwipeDirection.TOP);
    }

    public static void detectRight( View view, SwipeSingleCallback swipeSingleCallback){
        SwipeEvents evt = SwipeEvents.newInstance();
        evt.swipeSingleCallback = swipeSingleCallback;
        evt.view = view;
        evt.detectSingle(SwipeDirection.RIGHT);
    }

    public static void detectBottom( View view, SwipeSingleCallback swipeSingleCallback){
        SwipeEvents evt = SwipeEvents.newInstance();
        evt.swipeSingleCallback = swipeSingleCallback;
        evt.view = view;
        evt.detectSingle(SwipeDirection.BOTTOM);
    }
    public static void detectLeft( View view, SwipeSingleCallback swipeSingleCallback){
        SwipeEvents evt = SwipeEvents.newInstance();
        evt.swipeSingleCallback = swipeSingleCallback;
        evt.view = view;
        evt.detectSingle(SwipeDirection.LEFT);
    }

    private void detect( ){
        view.setOnTouchListener(this);
    }

    private void detectSingle( SwipeDirection direction ){
        this.detectSwipeDirection = direction;
        view.setOnTouchListener(this);
    }

    @Override
    public boolean onTouch(View view, MotionEvent event) {
        switch (event.getAction() ){
            case MotionEvent.ACTION_DOWN:
                x1 = event.getX();
                y1 = event.getY();
                break;
            case MotionEvent.ACTION_UP:
                x2 = event.getX();
                y2 = event.getY();
                SwipeDirection direction =null;

                float xDiff = x2-x1;
                float yDiff = y2- y1;
                if( Math.abs(xDiff) > Math.abs(yDiff) ){
                    if (x1<x2){
                        direction = SwipeDirection.RIGHT;
                    }else{
                        direction = SwipeDirection.LEFT;
                    }
                }else {
                    if (y1 > y2) {
                        direction = SwipeDirection.TOP;
                    } else {
                        direction = SwipeDirection.BOTTOM;
                    }
                }

                // Only trigger the requested event only if there
                if ( detectSwipeDirection !=null && swipeSingleCallback !=null ){
                    if ( direction == detectSwipeDirection ){
                        swipeSingleCallback.onSwipe();
                    }
                }else{
                    if ( direction == SwipeDirection.RIGHT ){
                        swipeCallback.onSwipeRight();
                    }
                    if ( direction == SwipeDirection.LEFT ){
                        swipeCallback.onSwipeLeft();
                    }
                    if ( direction == SwipeDirection.TOP ){
                        swipeCallback.onSwipeTop();
                    }
                    if ( direction == SwipeDirection.BOTTOM ){
                        swipeCallback.onSwipeBottom();
                    }
                }

                break;
        }
        return false;
    }

    public enum SwipeDirection{
        TOP, RIGHT, BOTTOM, LEFT
    }

    public interface SwipeCallback{
        public void onSwipeTop();
        public void onSwipeRight();
        public void onSwipeBottom();
        public void onSwipeLeft();
    }

    public interface SwipeSingleCallback{
        public void onSwipe();
    }
}

Change the class package name to match your project package name

With that you are good to go.

An example layout with the view we will be using to detect swipe events

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:id="@+id/swipeElement"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:background="#FFD"
        android:clickable="true">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="@dimen/abc_text_size_title_material"
            android:text="@string/swipe_element"
            android:layout_centerInParent="true"/>

    </RelativeLayout>
</LinearLayout>

Open the activity with the view you want to bind swipe events, have an object reference to the view as a variable like this:

public class SwipeActivity extends ActionBarActivity {
    RelativeLayout swipeElement;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_swipe);

        swipeElement = (RelativeLayout) findViewById( R.id.swipeElement );
    }
}

Listening to swipe events 

1: Listen to all the swipe events with one callback

SwipeEvents.detect( swipeElement, new SwipeEvents.SwipeCallback() {
	@Override
	public void onSwipeTop() {
		//Swiped top
	}

	@Override
	public void onSwipeRight() {
		//Swiped right
	}

	@Override
	public void onSwipeBottom() {
		//Swiped bottom
	}

	@Override
	public void onSwipeLeft() {
		//Swiped left
	}
});

2: Only detect a single swipe  - top/ bottom/ right or left

Available methods: detectTop, detectRight, detectBottom, detectLeft

SwipeEvents.detectTop(swipeElement, new SwipeEvents.SwipeSingleCallback() {
	@Override
	public void onSwipe() {
		// swiped top
	}
});

All the codes have been organized into one gist available from this https://gist.github.com/bmutinda/9578f70f1df9bd0687b8/

Happy coding….

Leave a Reply

Your email address will not be published. Required fields are marked *