我希望我的应用程序能够识别用户在手机屏幕上从右向左滑动。

如何做到这一点?


当前回答

@Mirek Rusin的回答很好。 但是,有一个小bug,需要修复

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;
                }

有什么不同?我们设置result = true,仅当我们检查了所有的需求(SWIPE_THRESHOLD和SWIPE_VELOCITY_THRESHOLD都是Ok的)。这是重要的,如果我们放弃滑动,如果一些需求没有实现,我们必须做smth在OnSwipeTouchListener的onTouchEvent方法!

其他回答

我知道从2012年开始有点晚了,但我希望它能帮助到一些人,因为我认为它比大多数答案都更短,更干净:

view.setOnTouchListener((v, event) -> {
        
int action = MotionEventCompat.getActionMasked(event);

switch(action) {
    case (MotionEvent.ACTION_DOWN) :
        Log.d(DEBUG_TAG,"Action was DOWN");
        return true;

    case (MotionEvent.ACTION_MOVE) :
        Log.d(DEBUG_TAG,"Action was MOVE");
        return true;

    case (MotionEvent.ACTION_UP) :
        Log.d(DEBUG_TAG,"Action was UP");
        return true;

    case (MotionEvent.ACTION_CANCEL) :
        Log.d(DEBUG_TAG,"Action was CANCEL");
        return true;

    case (MotionEvent.ACTION_OUTSIDE) :
        Log.d(DEBUG_TAG,"Movement occurred outside bounds " +
                "of current screen element");
        return true;

    default :
        return super.onTouchEvent(event);
}
    });

当然,你可以只留下相关的手势。

src: https://developer.android.com/training/gestures/detector

对@Mirek Rusin的回答做了一点修改,现在你可以检测多点触摸了。这段代码在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
    }
}}

在姿态。SWIPE_RIGHT和其他是唯一的整数标识符的手势,我用它来检测一种手势在我的活动:

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

这里的gesture是一个整型变量它包含了我之前传递的值。

为了添加一个onClick,下面是我所做的。

....
// 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

我正在使用Fragments,因此使用getActivity()作为上下文。这就是我实现它的方法——而且它很有效。


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();
            }
        });

爱德华·布雷的回答在科特林的使用

 view.setOnTouchListener(object: OnSwipeTouchListener(this) {
      override fun onSwipeLeft() {
        super.onSwipeLeft()
      }
      override fun onSwipeRight() {
        super.onSwipeRight()
      }
    }
 )

我的解决方案与上述类似,但我将手势处理抽象为一个抽象类OnGestureRegisterListener.java,其中包括滑动、单击和长按手势。

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;
        }

    }
}

像这样使用它。注意,您还可以轻松地传入您的View参数。

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);