Android: How to handle right to left swipe gestures

前端 未结 22 1173
日久生厌
日久生厌 2020-11-21 06:18

I want my app to recognize when a user swipes from right to left on the phone screen.

How to do this?

相关标签:
22条回答
  • 2020-11-21 07:13

    @Mirek Rusin answeir is very good. But, there is small bug, and fix is requried -

    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                boolean result = false;
                try {
                    float diffY = e2.getY() - e1.getY();
                    float diffX = e2.getX() - e1.getX();
                    if (Math.abs(diffX) > Math.abs(diffY)) {
                        if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                            if (diffX > 0) {
                                if (getOnSwipeListener() != null) {
                                    getOnSwipeListener().onSwipeRight();
                                }
                            } else {
                                if (getOnSwipeListener() != null) {
                                    getOnSwipeListener().onSwipeLeft();
                                }
                            }
                            result = true;
                        }
                    }
                    else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffY > 0) {
                            if (getOnSwipeListener() != null) {
                                getOnSwipeListener().onSwipeBottom();
                            }
                        } else {
                            if (getOnSwipeListener() != null) {
                                getOnSwipeListener().onSwipeTop();
                            }
                        }
                        result = true;
                    }
    

    What the difference? We set result = true, only if we have checked that all requrinments (both SWIPE_THRESHOLD and SWIPE_VELOCITY_THRESHOLD are Ok ). This is important if we discard swipe if some of requrinments are not achieved, and we have to do smth in onTouchEvent method of OnSwipeTouchListener!

    0 讨论(0)
  • 2020-11-21 07:13

    If you want to display some buttons with actions when an list item is swipe are a lot of libraries on the internet that have this behavior. I implemented the library that I found on the internet and I am very satisfied. It is very simple to use and very quick. I improved the original library and I added a new click listener for item click. Also I added font awesome library (http://fortawesome.github.io/Font-Awesome/) and now you can simply add a new item title and specify the icon name from font awesome.

    Here is the github link

    0 讨论(0)
  • 2020-11-21 07:16

    To add an onClick as well, here's what I did.

    ....
    // in OnSwipeTouchListener class
    
    private final class GestureListener extends SimpleOnGestureListener {
    
        .... // normal GestureListener  code
    
       @Override
        public boolean onSingleTapConfirmed(MotionEvent e) {
            onClick(); // my method
            return super.onSingleTapConfirmed(e);
        }
    
    } // end GestureListener class
    
        public void onSwipeRight() {
        }
    
        public void onSwipeLeft() {
        }
    
        public void onSwipeTop() {
        }
    
        public void onSwipeBottom() {
        }
    
        public void onClick(){ 
        }
    
    
        // as normal
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return gestureDetector.onTouchEvent(event);
    }
    
    } // end OnSwipeTouchListener class
    

    I'm using Fragments, so using getActivity() for context. This is how I implemented it - and it works.


    myLayout.setOnTouchListener(new OnSwipeTouchListener(getActivity()) {
                public void onSwipeTop() {
                    Toast.makeText(getActivity(), "top", Toast.LENGTH_SHORT).show();
                }
                public void onSwipeRight() {
                    Toast.makeText(getActivity(), "right", Toast.LENGTH_SHORT).show();
                }
                public void onSwipeLeft() {
                    Toast.makeText(getActivity(), "left", Toast.LENGTH_SHORT).show();
                }
                public void onSwipeBottom() {
                    Toast.makeText(getActivity(), "bottom", Toast.LENGTH_SHORT).show();
                }
    
                public void onClick(){
                    Toast.makeText(getActivity(), "clicked", Toast.LENGTH_SHORT).show();
                }
            });
    
    0 讨论(0)
  • 2020-11-21 07:16

    A little modification of @Mirek Rusin answer and now you can detect multitouch swipes. This code is on Kotlin:

    class OnSwipeTouchListener(ctx: Context, val onGesture: (gestureCode: Int) -> Unit) : OnTouchListener {
    
    private val SWIPE_THRESHOLD = 200
    private val SWIPE_VELOCITY_THRESHOLD = 200
    
    private val gestureDetector: GestureDetector
    
    var fingersCount = 0
    
    fun resetFingers() {
        fingersCount = 0
    }
    
    init {
        gestureDetector = GestureDetector(ctx, GestureListener())
    }
    
    override fun onTouch(v: View, event: MotionEvent): Boolean {
        if (event.pointerCount > fingersCount) {
            fingersCount = event.pointerCount
        }
        return gestureDetector.onTouchEvent(event)
    }
    
    private inner class GestureListener : SimpleOnGestureListener() {
    
        override fun onDown(e: MotionEvent): Boolean {
            return true
        }
    
        override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean {
            var result = false
            try {
                val diffY = e2.y - e1.y
                val diffX = e2.x - e1.x
                if (Math.abs(diffX) > Math.abs(diffY)) {
                    if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffX > 0) {
                            val gesture = when (fingersCount) {
                                1 -> Gesture.SWIPE_RIGHT
                                2 -> Gesture.TWO_FINGER_SWIPE_RIGHT
                                3 -> Gesture.THREE_FINGER_SWIPE_RIGHT
                                else -> -1
                            }
                            if (gesture > 0) {
                                onGesture.invoke(gesture)
                            }
                        } else {
                            val gesture = when (fingersCount) {
                                1 -> Gesture.SWIPE_LEFT
                                2 -> Gesture.TWO_FINGER_SWIPE_LEFT
                                3 -> Gesture.THREE_FINGER_SWIPE_LEFT
                                else -> -1
                            }
                            if (gesture > 0) {
                                onGesture.invoke(gesture)
                            }
                        }
                        resetFingers()
                    }
                } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                    if (diffY > 0) {
                        val gesture = when (fingersCount) {
                            1 ->  Gesture.SWIPE_DOWN
                            2 -> Gesture.TWO_FINGER_SWIPE_DOWN
                            3 -> Gesture.THREE_FINGER_SWIPE_DOWN
                            else -> -1
                        }
                        if (gesture > 0) {
                            onGesture.invoke(gesture)
                        }
                    } else {
                        val gesture = when (fingersCount) {
                            1 ->  Gesture.SWIPE_UP
                            2 -> Gesture.TWO_FINGER_SWIPE_UP
                            3 -> Gesture.THREE_FINGER_SWIPE_UP
                            else -> -1
                        }
                        if (gesture > 0) {
                            onGesture.invoke(gesture)
                        }
                    }
                    resetFingers()
                }
                result = true
    
            } catch (exception: Exception) {
                exception.printStackTrace()
            }
    
            return result
        }
    }}
    

    Where Gesture.SWIPE_RIGHT and others are unique integer indentificator of gesture that I`m using to detect kind of gesture later in my activity:

    rootView?.setOnTouchListener(OnSwipeTouchListener(this, {
        gesture -> log(Gesture.parseName(this, gesture))
    }))
    

    So you see gesture here is an integer variable that holds value I have passed before.

    0 讨论(0)
  • 2020-11-21 07:17

    the usage of Edward Brey's answer in Kotlin

     view.setOnTouchListener(object: OnSwipeTouchListener(this) {
          override fun onSwipeLeft() {
            super.onSwipeLeft()
          }
          override fun onSwipeRight() {
            super.onSwipeRight()
          }
        }
     )
    
    0 讨论(0)
  • 2020-11-21 07:18

    You don't need complicated calculations. It can be done just by using OnGestureListener interface from GestureDetector class.

    Inside onFling method you can detect all four directions like this:

    MyGestureListener.java:

    import android.util.Log;
    import android.view.GestureDetector;
    import android.view.MotionEvent;
    
    public class MyGestureListener implements GestureDetector.OnGestureListener{
    
        private static final long VELOCITY_THRESHOLD = 3000;
    
        @Override
        public boolean onDown(final MotionEvent e){ return false; }
    
        @Override
        public void onShowPress(final MotionEvent e){ }
    
        @Override
        public boolean onSingleTapUp(final MotionEvent e){ return false; }
    
        @Override
        public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX,
                            final float distanceY){ return false; }
    
        @Override
        public void onLongPress(final MotionEvent e){ }
    
        @Override
        public boolean onFling(final MotionEvent e1, final MotionEvent e2,
                           final float velocityX,
                           final float velocityY){
    
            if(Math.abs(velocityX) < VELOCITY_THRESHOLD 
                        && Math.abs(velocityY) < VELOCITY_THRESHOLD){
                return false;//if the fling is not fast enough then it's just like drag
            }
    
            //if velocity in X direction is higher than velocity in Y direction,
            //then the fling is horizontal, else->vertical
            if(Math.abs(velocityX) > Math.abs(velocityY)){
                if(velocityX >= 0){
                    Log.i("TAG", "swipe right");
                }else{//if velocityX is negative, then it's towards left
                    Log.i("TAG", "swipe left");
                }
            }else{
                if(velocityY >= 0){
                    Log.i("TAG", "swipe down");
                }else{
                    Log.i("TAG", "swipe up");
                }
            }
    
            return true;
        }
    }
    

    usage:

    GestureDetector mDetector = new GestureDetector(MainActivity.this, new MyGestureListener());
    
    view.setOnTouchListener(new View.OnTouchListener(){
        @Override
        public boolean onTouch(final View v, final MotionEvent event){
            return mDetector.onTouchEvent(event);
        }
    });
    
    0 讨论(0)
提交回复
热议问题