Android: How to handle right to left swipe gestures

前端 未结 22 1172
日久生厌
日久生厌 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:20

    @Edward Brey's method works great. If someone would also like to copy & paste the imports for the OnSwipeTouchListener, here they are:

     import android.content.Context;
     import android.view.GestureDetector;
     import android.view.GestureDetector.SimpleOnGestureListener;
     import android.view.MotionEvent;
     import android.view.View;
     import android.view.View.OnTouchListener;
    
    0 讨论(0)
  • 2020-11-21 07:21

    Use SwipeListView and let it handle the gesture detection for you.

    Screenshot

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

    My solution is similar to those above but I have abstracted the gesture handling into an abstract class OnGestureRegisterListener.java, which includes swipe, click and long click gestures.

    OnGestureRegisterListener.java

    public abstract class OnGestureRegisterListener implements View.OnTouchListener {
    
        private final GestureDetector gestureDetector;
        private View view;
    
        public OnGestureRegisterListener(Context context) {
            gestureDetector = new GestureDetector(context, new GestureListener());
        }
    
        @Override
        public boolean onTouch(View view, MotionEvent event) {
            this.view = view;
            return gestureDetector.onTouchEvent(event);
        }
    
        public abstract void onSwipeRight(View view);
        public abstract void onSwipeLeft(View view);
        public abstract void onSwipeBottom(View view);
        public abstract void onSwipeTop(View view);
        public abstract void onClick(View view);
        public abstract boolean onLongClick(View view);
    
        private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
    
            private static final int SWIPE_THRESHOLD = 100;
            private static final int SWIPE_VELOCITY_THRESHOLD = 100;
    
            @Override
            public boolean onDown(MotionEvent e) {
                return true;
            }
    
            @Override
            public void onLongPress(MotionEvent e) {
                onLongClick(view);
                super.onLongPress(e);
            }
    
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                onClick(view);
                return super.onSingleTapUp(e);
            }
    
            @Override
            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) {
                                onSwipeRight(view);
                            } else {
                                onSwipeLeft(view);
                            }
                            result = true;
                        }
                    }
                    else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
                        if (diffY > 0) {
                            onSwipeBottom(view);
                        } else {
                            onSwipeTop(view);
                        }
                        result = true;
                    }
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
                return result;
            }
    
        }
    }
    

    And use it like so. Note that you can also easily pass in your View parameter.

    OnGestureRegisterListener onGestureRegisterListener = new OnGestureRegisterListener(this) {
        public void onSwipeRight(View view) {
            // Do something
        }
        public void onSwipeLeft(View view) {
            // Do something
        }
        public void onSwipeBottom(View view) {
            // Do something
        }
        public void onSwipeTop(View view) {
            // Do something
        }
        public void onClick(View view) {
            // Do something
        }
        public boolean onLongClick(View view) { 
            // Do something
            return true;
        }
    };
    
    Button button = findViewById(R.id.my_button);
    button.setOnTouchListener(onGestureRegisterListener);
    
    0 讨论(0)
  • 2020-11-21 07:24

    This issue still exists. An OnTouchListener with an OnSwipeTouchListener solves it in a simple way:

    myView.setOnTouchListener(
        new View.OnTouchListener() {
            public boolean onTouch(View v, MotionEvent event) {
                if(!swipe.onTouch(v, event)) {
                    if (event.getAction() == MotionEvent.ACTION_UP) {
                        // your code here
    
                        return true;
                    } else if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        // your code here
    
                        return true;
                    }
                }
                return false;
            }
    
        }
    );
    

    where swipe refers to a class which records whether swipe methods have been invoked, then forwards events to the delegate OnSwipeTouchListener.

    private class DirtyOnSwipeTouchListener extends OnSwipeTouchListener {
        private boolean dirty = false;
        private OnSwipeTouchListener delegate;
    
        public DirtyOnSwipeTouchListener(Context ctx, OnSwipeTouchListener delegate) {
            super(ctx);
    
            this.delegate = delegate;
        }
    
        private void reset() {
            dirty = false;
        }
    
        public void onSwipeTop() {
            dirty = true;
            delegate.onSwipeTop();
        }
    
        public void onSwipeRight() {
            dirty = true;
            delegate.onSwipeRight();
        }
    
        public void onSwipeLeft() {
            dirty = true;
            delegate.onSwipeLeft();
        }
    
        public void onSwipeBottom() {
            dirty = true;
            delegate.onSwipeBottom();
        }
    
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            try {
                super.onTouch(v, event);
    
                return dirty;
            } finally {
                dirty = false;
            }
    
        }
    };
    
    0 讨论(0)
提交回复
热议问题