我希望我的应用程序能够识别用户在手机屏幕上从右向左滑动。
如何做到这一点?
我希望我的应用程序能够识别用户在手机屏幕上从右向左滑动。
如何做到这一点?
当前回答
扩展Mirek的回答,当你想在滚动视图中使用滑动手势时。默认情况下,滚动视图的触摸监听器被禁用,因此滚动动作不会发生。为了解决这个问题,您需要重写Activity的dispatchTouchEvent方法,并在您完成自己的侦听器后返回该方法的继承版本。
为了对Mirek的代码做一些修改: 我在OnSwipeTouchListener中添加了一个gestureDetector getter。
public GestureDetector getGestureDetector(){
return gestureDetector;
}
在Activity中声明OnSwipeTouchListener作为类范围的字段。
OnSwipeTouchListener onSwipeTouchListener;
相应修改用法代码:
onSwipeTouchListener = new OnSwipeTouchListener(MyActivity.this) {
public void onSwipeTop() {
Toast.makeText(MyActivity.this, "top", Toast.LENGTH_SHORT).show();
}
public void onSwipeRight() {
Toast.makeText(MyActivity.this, "right", Toast.LENGTH_SHORT).show();
}
public void onSwipeLeft() {
Toast.makeText(MyActivity.this, "left", Toast.LENGTH_SHORT).show();
}
public void onSwipeBottom() {
Toast.makeText(MyActivity.this, "bottom", Toast.LENGTH_SHORT).show();
}
});
imageView.setOnTouchListener(onSwipeTouchListener);
并覆盖活动内部的dispatchTouchEvent方法:
@Override
public boolean dispatchTouchEvent(MotionEvent ev){
swipeListener.getGestureDetector().onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
现在滚动和滑动动作都可以工作了。
其他回答
这段代码检测左右滑动,避免了废弃的API调用,并对之前的答案进行了其他改进。
/**
* Detects left and right swipes across a view.
*/
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener(Context context) {
gestureDetector = new GestureDetector(context, new GestureListener());
}
public void onSwipeLeft() {
}
public void onSwipeRight() {
}
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_DISTANCE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
float distanceX = e2.getX() - e1.getX();
float distanceY = e2.getY() - e1.getY();
if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceX > 0)
onSwipeRight();
else
onSwipeLeft();
return true;
}
return false;
}
}
}
像这样使用它:
view.setOnTouchListener(new OnSwipeTouchListener(context) {
@Override
public void onSwipeLeft() {
// Whatever
}
});
为了添加一个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();
}
});
我的解决方案与上述类似,但我将手势处理抽象为一个抽象类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);
为了有点击监听器,双击监听器,OnLongPress监听器,向左滑动,向右滑动,向上滑动,在单视图上向下滑动,你需要setOnTouchListener。也就是说,
view.setOnTouchListener(new OnSwipeTouchListener(MainActivity.this) {
@Override
public void onClick() {
super.onClick();
// your on click here
}
@Override
public void onDoubleClick() {
super.onDoubleClick();
// your on onDoubleClick here
}
@Override
public void onLongClick() {
super.onLongClick();
// your on onLongClick here
}
@Override
public void onSwipeUp() {
super.onSwipeUp();
// your swipe up here
}
@Override
public void onSwipeDown() {
super.onSwipeDown();
// your swipe down here.
}
@Override
public void onSwipeLeft() {
super.onSwipeLeft();
// your swipe left here.
}
@Override
public void onSwipeRight() {
super.onSwipeRight();
// your swipe right here.
}
});
}
为此,你需要实现OnTouchListener的OnSwipeTouchListener类。
public class OnSwipeTouchListener implements View.OnTouchListener {
private GestureDetector gestureDetector;
public OnSwipeTouchListener(Context c) {
gestureDetector = new GestureDetector(c, new GestureListener());
}
public boolean onTouch(final View view, final MotionEvent motionEvent) {
return gestureDetector.onTouchEvent(motionEvent);
}
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 boolean onSingleTapUp(MotionEvent e) {
onClick();
return super.onSingleTapUp(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
onDoubleClick();
return super.onDoubleTap(e);
}
@Override
public void onLongPress(MotionEvent e) {
onLongClick();
super.onLongPress(e);
}
// Determines the fling velocity and then fires the appropriate swipe event accordingly
@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();
} else {
onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeDown();
} else {
onSwipeUp();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeUp() {
}
public void onSwipeDown() {
}
public void onClick() {
}
public void onDoubleClick() {
}
public void onLongClick() {
}
}
如果你还需要处理点击事件,这里做一些修改:
public class OnSwipeTouchListener implements OnTouchListener {
private final GestureDetector gestureDetector = new GestureDetector(new GestureListener());
public boolean onTouch(final View v, final MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@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) {
result = onSwipeRight();
} else {
result = onSwipeLeft();
}
}
} else {
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
result = onSwipeBottom();
} else {
result = onSwipeTop();
}
}
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public boolean onSwipeRight() {
return false;
}
public boolean onSwipeLeft() {
return false;
}
public boolean onSwipeTop() {
return false;
}
public boolean onSwipeBottom() {
return false;
}
}
以及示例用法:
background.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
toggleSomething();
}
});
background.setOnTouchListener(new OnSwipeTouchListener() {
public boolean onSwipeTop() {
Toast.makeText(MainActivity.this, "top", Toast.LENGTH_SHORT).show();
return true;
}
public boolean onSwipeRight() {
Toast.makeText(MainActivity.this, "right", Toast.LENGTH_SHORT).show();
return true;
}
public boolean onSwipeLeft() {
Toast.makeText(MainActivity.this, "left", Toast.LENGTH_SHORT).show();
return true;
}
public boolean onSwipeBottom() {
Toast.makeText(MainActivity.this, "bottom", Toast.LENGTH_SHORT).show();
return true;
}
});