Search code examples
androidswipe

Android view with multi-directional swipe gestures


I have a view with a TextView containing long text, so the view has to give the user the facility of scrolling through the text.

Also, this TextView must allow swipe right and left on all instances of the view.

I've got the scroll working with scollingMovementMethod but the left and right swipe doesn't work.


Solution

  • For enabling swipe gesture left,right,up or down, follow the below steps:

    Step 1: Create a java file SimpleGestureFilter

    import android.app.Activity;
    import android.view.GestureDetector;
    import android.view.MotionEvent;
    
    /**
    * Created by nihal on 1/21/2016.
    */
    public class SimpleGestureFilter extends  
     GestureDetector.SimpleOnGestureListener {
    public final static int SWIPE_UP= 1;
    public final static int SWIPE_DOWN= 2;
    public final static int SWIPE_LEFT= 3;
    public final static int SWIPE_RIGHT = 4;
    public final static int MODE_TRANSPARENT = 0;
    public final static int MODE_SOLID= 1;
    public final static int MODE_DYNAMIC= 2;
    private final static int ACTION_FAKE = -13; //just an unlikely number
    private int swipe_Min_Distance = 100;
    private int swipe_Max_Distance = 350;
    private int swipe_Min_Velocity = 100;
    private int mode = MODE_DYNAMIC;
    private boolean running = true;
    private boolean tapIndicator = false;
    private Activity context;
    private GestureDetector detector;
    private SimpleGestureListener listener;
    public SimpleGestureFilter(Activity context,SimpleGestureListener sgl) {
    
        this.context = context;
        this.detector = new GestureDetector(context, this);
        this.listener = sgl;
    }
    public void onTouchEvent(MotionEvent event){
    
        if(!this.running)
            return;
    
        boolean result = this.detector.onTouchEvent(event);
    
        if(this.mode == MODE_SOLID)
            event.setAction(MotionEvent.ACTION_CANCEL);
        else if (this.mode == MODE_DYNAMIC) {
    
            if(event.getAction() == ACTION_FAKE)
                event.setAction(MotionEvent.ACTION_UP);
            else if (result)
                event.setAction(MotionEvent.ACTION_CANCEL);
            else if(this.tapIndicator){
                event.setAction(MotionEvent.ACTION_DOWN);
                this.tapIndicator = false;
            }
    
        }
        //else just do nothing, it's Transparent
    }
    public void setMode(int m){
        this.mode = m;
    }
    public int getMode(){
        return this.mode;
    }
    public void setEnabled(boolean status){
        this.running = status;
    }
    private static final int SWIPE_MIN_DISTANCE = 120;
    private static final int SWIPE_MAX_OFF_PATH = 250;
    private static final int SWIPE_THRESHOLD_VELOCITY = 200;
    
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
                           float velocityY) {
    
        try {
            if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
                return false;
            }
            // right to left swipe
            if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { // right to left
                this.listener.onSwipe(SWIPE_LEFT);
    
    
    
            }if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { // right to left
                this.listener.onSwipe(SWIPE_RIGHT);
    
    
    
            } else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
                    && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { //    bottom to up
                this.listener.onSwipe(SWIPE_UP);
    
    
    
            }
    
        } catch (Exception e) {
    
        }
        return false;
    }
    
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        this.tapIndicator = true;
        return false;
    }
    @Override
    public boolean onDoubleTap(MotionEvent arg0) {
        this.listener.onDoubleTap();;
        return true;
    }
    
    @Override
    public boolean onDoubleTapEvent(MotionEvent arg0) {
        return true;
    }
    @Override
    public boolean onSingleTapConfirmed(MotionEvent arg0) {
    
        if(this.mode == MODE_DYNAMIC){// we owe an ACTION_UP, so we fake an      
            arg0.setAction(ACTION_FAKE);//action which will be converted to an ACTION_UP later.                                   
            this.context.dispatchTouchEvent(arg0);
        }
        return false;
    }
    
    public interface SimpleGestureListener{
        void onSwipe(int direction);
        void onDoubleTap();
    }
    
    }
    

    Step 2: Extend AppCompatActivity and implement SimpleGestureFilter.SimpleGestureListener in your Activity like this:

    public class YourActivity extends AppCompatActivity implements     
    SimpleGestureFilter.SimpleGestureListener {
         //inside of activity, code here
      }
    

    Step 3: define

    private SimpleGestureFilter detector;
    

    Step4: in your onCreate method add this:

    detector = new SimpleGestureFilter(this,this);
    

    now YourActivity should look like this

    public class YourActivity extends AppCompatActivity implements    
    
    SimpleGestureFilter.SimpleGestureListener {
    
    private SimpleGestureFilter detector;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.yourlayout);
        detector = new SimpleGestureFilter(this,this);
    
    }
    
     // add codes for Swipe Gesture here
    
    
     }
    

    Step 5: Add codes for Swipe Gesture in YourActivity

    public class sources extends AppCompatActivity implements 
    SimpleGestureFilter.SimpleGestureListener {
    
    private SimpleGestureFilter detector;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sources);
        detector = new SimpleGestureFilter(this,this);
    
    }
    
    
    
    @Override
    public boolean dispatchTouchEvent(MotionEvent me){
    
        this.detector.onTouchEvent(me);
    
        return super.dispatchTouchEvent(me);
    
    }
    @Override
    
    public void onSwipe(int direction) {
        String str = "";
    
    
    
        switch (direction) {
    
            case SimpleGestureFilter.SWIPE_RIGHT :
    
                //**code** here for what you wanna do with **Right Swipe**
    
            case SimpleGestureFilter.SWIPE_LEFT :
               //**code** here for what you wanna do with **Left Swipe**
    
    
            case SimpleGestureFilter.SWIPE_DOWN :
    
                break;
    
            case SimpleGestureFilter.SWIPE_UP :
    
                break;
    
        }
    
    
    
    }
    
    
    
    
    @Override
    
    public void onDoubleTap() {
    
        Toast.makeText(this, "Try swiping left", Toast.LENGTH_LONG).show();
    
    }
    

    Follow all the above steps correctly, you will be able to make swipe gestures work