如何在 Android 中检测向左或向右滑动?
Posted
技术标签:
【中文标题】如何在 Android 中检测向左或向右滑动?【英文标题】:How to detect the swipe left or Right in Android? 【发布时间】:2011-10-02 11:57:27 【问题描述】:我在 android 中有一个 EditText
视图。在此我想检测向左或向右滑动。我可以使用下面的代码在空白处获取它。但是当我在EditText
上滑动时,这不起作用。我怎么做?如果我做错了什么,请告诉我。谢谢。
使用的代码:
switch (touchevent.getAction())
case MotionEvent.ACTION_DOWN:
oldTouchValue = touchevent.getX();
break;
case MotionEvent.ACTION_UP:
float currentX = touchevent.getX();
if (oldTouchValue < currentX)
// swiped left
if (oldTouchValue > currentX )
swiped right
break;
【问题讨论】:
此需求的有用教程techrepublic.com/blog/software-engineer/… 【参考方案1】:这里是使用数据绑定的 kotlin 中任何视图的通用向左滑动检测器
@BindingAdapter("onSwipeLeft")
fun View.setOnSwipeLeft(runnable: Runnable)
setOnTouchListener(object : View.OnTouchListener
var x0 = 0F; var y0 = 0F; var t0 = 0L
val defaultClickDuration = 200
override fun onTouch(v: View?, motionEvent: MotionEvent?): Boolean
motionEvent?.let event ->
when(event.action)
MotionEvent.ACTION_DOWN ->
x0 = event.x; y0 = event.y; t0 = System.currentTimeMillis()
MotionEvent.ACTION_UP ->
val x1 = event.x; val y1 = event.y; val t1 = System.currentTimeMillis()
if (x0 == x1 && y0 == y1 && (t1 - t0) < defaultClickDuration)
performClick()
return false
if (x0 > x1) runnable.run()
else ->
return true
)
然后在你的布局中使用它:
app:onSwipeLeft="@() -> viewModel.swipeLeftHandler()"
【讨论】:
【参考方案2】:您应该从View.OnTouchListener
扩展一个类并通过覆盖它来处理onTouch
方法。
interface SwipeListener
fun onSwipeLeft()
fun onSwipeRight()
class SwipeGestureListener internal constructor(
private val listener: SwipeListener,
private val minDistance: Int = DEFAULT_SWIPE_MIN_DISTANCE
) : View.OnTouchListener
companion object
const val DEFAULT_SWIPE_MIN_DISTANCE = 200
private var anchorX = 0F
override fun onTouch(view: View, event: MotionEvent): Boolean
when (event.action)
MotionEvent.ACTION_DOWN ->
anchorX = event.x
return true
MotionEvent.ACTION_UP ->
if (abs(event.x - anchorX) > minDistance)
if (event.x > anchorX)
listener.onSwipeRight()
else
listener.onSwipeLeft()
return true
return view.performClick()
您可以在 Activity
或 Fragment
中轻松实现它。
class MainActivity : AppCompatActivity(), SwipeListener
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
viewGroup.setOnTouchListener(SwipeGestureListener(this))
override fun onSwipeLeft()
Toast.makeText(this, "Swipe Left", Toast.LENGTH_SHORT).show()
override fun onSwipeRight()
Toast.makeText(this, "Swipe Right", Toast.LENGTH_SHORT).show()
【讨论】:
【参考方案3】:简短易懂的版本:
1.首先创建这个抽象类
public abstract class HorizontalSwipeListener implements View.OnTouchListener
private float firstX;
private int minDistance;
HorizontalSwipeListener(int minDistance)
this.minDistance = minDistance;
abstract void onSwipeRight();
abstract void onSwipeLeft();
@Override
public boolean onTouch(View view, MotionEvent event)
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
firstX = event.getX();
return true;
case MotionEvent.ACTION_UP:
float secondX = event.getX();
if (Math.abs(secondX - firstX) > minDistance)
if (secondX > firstX)
onSwipeLeft();
else
onSwipeRight();
return true;
return view.performClick();
2.然后创建一个具体的类来实现你所需要的:
public class SwipeListener extends HorizontalSwipeListener
public SwipeListener()
super(200);
@Override
void onSwipeRight()
System.out.println("right");
@Override
void onSwipeLeft()
System.out.println("left");
【讨论】:
【参考方案4】:最简单的从左到右滑动检测器:
在您的活动类中添加以下属性:
private float x1,x2;
static final int MIN_DISTANCE = 150;
并覆盖onTouchEvent()
方法:
@Override
public boolean onTouchEvent(MotionEvent event)
switch(event.getAction())
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
x2 = event.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE)
Toast.makeText(this, "left2right swipe", Toast.LENGTH_SHORT).show ();
else
// consider as something else - a screen tap for example
break;
return super.onTouchEvent(event);
【讨论】:
谢谢它的工作,但如果有滚动视图,你能告诉我如何让它工作吗?getAction()
返回action类型和指针索引的混合数据,用getActionMasked()
只返回action类型不是更好吗?
此解决方案已过时。现在你可以使用 onFling 手势了。
@LS_ 考虑自定义 ScrollView 并放置 onInterceptTouchEvent 来管理哪些事件应该到达子视图。【参考方案5】:
经过一整天的时间研究这个功能终于能够得到正确的答案。
首先,创建以下类:
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by hoshyar on 1/19/17.
*/
public class SwipeDetector implements View.OnTouchListener
public static enum Action
LR, // Left to Right
RL, // Right to Left
TB, // Top to bottom
BT, // Bottom to Top
None // when no action was detected
private static final String logTag = "Swipe";
private static final int MIN_DISTANCE = 100;
private float downX, downY, upX, upY;
private Action mSwipeDetected = Action.None;
public boolean swipeDetected()
return mSwipeDetected != Action.None;
public Action getAction()
return mSwipeDetected;
@Override
public boolean onTouch(View v, MotionEvent event)
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
mSwipeDetected = Action.None;
return false;
case MotionEvent.ACTION_MOVE:
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
Log.i(logTag,String.valueOf(deltaX));
Log.i(logTag,String.valueOf(deltaX));
if (deltaY>0 && deltaY<10 && deltaX<0 || deltaY==0 && deltaX>-15 && deltaX<0)
Log.i(logTag,"to right");
if (deltaY>=0 && deltaY<10 && deltaX>0 || deltaY<0 && deltaX>15 && deltaX<40)
Log.i(logTag,"to left");
if (Math.abs(deltaX) > MIN_DISTANCE)
// left or right
if (deltaX < 0)
mSwipeDetected = Action.LR;
return false;
if (deltaX > 0)
mSwipeDetected = Action.RL;
return false;
else if (Math.abs(deltaY) > MIN_DISTANCE)
if (deltaY < 0)
Log.i(logTag,"to bottom");
mSwipeDetected = Action.TB;
return false;
if (deltaY > 0)
Log.i(logTag,"to up");
mSwipeDetected = Action.BT;
return false;
return true;
return false;
最后在您要应用的对象上。 我的例子:
SwipeDetector swipeDetector = new SwipeDetector();
listView.setOnTouchListener(swipeDetector);
祝你好运。
【讨论】:
但是如何将事件返回给班级?【参考方案6】:这可能会对你有所帮助...
private final GestureDetector.SimpleOnGestureListener onGestureListener = new GestureDetector.SimpleOnGestureListener()
@Override
public boolean onDoubleTap(MotionEvent e)
Log.i("gestureDebug333", "doubleTapped:" + e);
return super.onDoubleTap(e);
@Override
public boolean onDoubleTapEvent(MotionEvent e)
Log.i("gestureDebug333", "doubleTappedEvent:" + e);
return super.onDoubleTapEvent(e);
@Override
public boolean onDown(MotionEvent e)
Log.i("gestureDebug333", "onDown:" + e);
return super.onDown(e);
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
Log.i("gestureDebug333", "flinged:" + e1 + "---" + e2);
Log.i("gestureDebug333", "fling velocity:" + velocityX + "---" + velocityY);
if (e1.getAction() == MotionEvent.ACTION_DOWN && e1.getX() > (e2.getX() + 300))
// Toast.makeText(context, "flinged right to left", Toast.LENGTH_SHORT).show();
goForward();
if (e1.getAction() == MotionEvent.ACTION_DOWN && e2.getX() > (e1.getX() + 300))
//Toast.makeText(context, "flinged left to right", Toast.LENGTH_SHORT).show();
goBack();
return super.onFling(e1, e2, velocityX, velocityY);
@Override
public void onLongPress(MotionEvent e)
super.onLongPress(e);
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY)
return super.onScroll(e1, e2, distanceX, distanceY);
@Override
public void onShowPress(MotionEvent e)
super.onShowPress(e);
@Override
public boolean onSingleTapConfirmed(MotionEvent e)
return super.onSingleTapConfirmed(e);
@Override
public boolean onSingleTapUp(MotionEvent e)
return super.onSingleTapUp(e);
;
【讨论】:
【参考方案7】:如果您想从滑动开始捕获事件,您可以使用 MotionEvent.ACTION_MOVE 并存储第一个值进行比较
private float upX1;
private float upX2;
private float upY1;
private float upY2;
private boolean isTouchCaptured = false;
static final int min_distance = 100;
viewObject.setOnTouchListener(new View.OnTouchListener()
@Override
public boolean onTouch(View v, MotionEvent event)
switch (event.getAction())
case MotionEvent.ACTION_MOVE:
downX = event.getX();
downY = event.getY();
if (!isTouchCaptured)
upX1 = event.getX();
upY1 = event.getY();
isTouchCaptured = true;
else
upX2 = event.getX();
upY2 = event.getY();
float deltaX = upX1 - upX2;
float deltaY = upY1 - upY2;
//HORIZONTAL SCROLL
if (Math.abs(deltaX) > Math.abs(deltaY))
if (Math.abs(deltaX) > min_distance)
// left or right
if (deltaX < 0)
return true;
if (deltaX > 0)
return true;
else
//not long enough swipe...
return false;
//VERTICAL SCROLL
else
if (Math.abs(deltaY) > min_distance)
// top or down
if (deltaY < 0)
return false;
if (deltaY > 0)
return false;
else
//not long enough swipe...
return false;
return false;
case MotionEvent.ACTION_UP:
isTouchCaptured = false;
return false;
);
【讨论】:
假设我有一个像Toast.makeText(MainAcivity.this, "top to down" + increaseValue, Toast.LENGTH_SHORT).show();
这样的 Toast,她如何通过单次滑动来添加值 min=0 和 max=10。【参考方案8】:
我认为你想要的东西叫做一掷千金。 MotionEvents 可用于确定投掷的方向。
public class MainActivity extends Activity implements GestureDetector.OnGestureListener
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.stellar_layout);
mDetector = new GestureDetectorCompat(this, this);
@Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY)
Log.d(tag, "onFling:\n " + event1.toString()+ "\n " + event2.toString());
/* prints the following
MotionEvent action=ACTION_DOWN, id[0]=0, x[0]=297.0, y[0]=672.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=488341979, downTime=488341979, deviceId=6, source=0x1002
MotionEvent action=ACTION_UP, id[0]=0, x[0]=560.0, y[0]=583.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=488342047, downTime=488341979, deviceId=6, source=0x1002
*/
return true;
http://developer.android.com/training/gestures/detector.html
【讨论】:
【参考方案9】:检测四个方向的滑动
private float x1,x2,y1,y2;
static final int MIN_DISTANCE = 70;
和
switch(pSceneTouchEvent.getAction())
case MotionEvent.ACTION_DOWN:
x1 = pSceneTouchEvent.getX();
y1 = pSceneTouchEvent.getY();
break;
case MotionEvent.ACTION_UP:
x2 = pSceneTouchEvent.getX();
y2 = pSceneTouchEvent.getY();
float deltaX = x2 - x1;
float deltaY = y2 - y1;
if (deltaX > MIN_DISTANCE)
swipeLeftToRight();
else if( Math.abs(deltaX) > MIN_DISTANCE)
swipeRightToLeft();
else if(deltaY > MIN_DISTANCE)
swipeTopToBottom();
else if( Math.abs(deltaY) > MIN_DISTANCE)
swipeBottopmToTop();
break;
【讨论】:
【参考方案10】:最好的答案是@Gal Rom 的。有更多关于它的信息: 触摸事件首先返回子视图。如果您为它们定义 onClick 或 onTouch 侦听器,则父视图(例如片段)将不会收到任何触摸侦听器。所以如果你想在这种情况下为片段定义滑动监听器,你必须在一个新的类中实现它:
package com.neganet.QRelations.fragments;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.FrameLayout;
public class SwipeListenerFragment extends FrameLayout
private float x1,x2;
static final int MIN_DISTANCE=150;
private onSwipeEventDetected mSwipeDetectedListener;
public SwipeListenerFragment(Context context)
super(context);
public SwipeListenerFragment(Context context, AttributeSet attrs)
super(context, attrs);
public SwipeListenerFragment(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
boolean result=false;
switch(ev.getAction())
case MotionEvent.ACTION_DOWN:
x1 = ev.getX();
break;
case MotionEvent.ACTION_UP:
x2 = ev.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE)
if(deltaX<0)
result=true;
if(mSwipeDetectedListener!=null)
mSwipeDetectedListener.swipeLeftDetected();
else if(deltaX>0)
result=true;
if(mSwipeDetectedListener!=null)
mSwipeDetectedListener.swipeRightDetected();
break;
return result;
public interface onSwipeEventDetected
public void swipeLeftDetected();
public void swipeRightDetected();
public void registerToSwipeEvents(onSwipeEventDetected listener)
this.mSwipeDetectedListener=listener;
我改变了@Gal Rom 的班级。所以它可以检测左右滑动,特别是它在检测后返回 onInterceptTouchEvent true。这很重要,因为如果我们有时不这样做,子视图可能会收到事件,并且 Swipe for fragment 和 onClick for child view(例如)都会运行并导致一些问题。 制作完此类后,您必须更改片段 xml 文件:
<com.neganet.QRelations.fragments.SwipeListenerFragment xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_
android:id="@+id/main_list_layout"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_ tools:context="com.neganet.QRelations.fragments.mainList"
android:background="@color/main_frag_back">
<!-- TODO: Update blank fragment layout -->
<android.support.v7.widget.RecyclerView
android:id="@+id/farazList"
android:scrollbars="horizontal"
android:layout_
android:layout_
android:layout_gravity="left|center_vertical" />
</com.neganet.QRelations.fragments.SwipeListenerFragment>
你看到开始标签是我们创建的类。现在在片段类中:
View view=inflater.inflate(R.layout.fragment_main_list, container, false);
SwipeListenerFragment tdView=(SwipeListenerFragment) view;
tdView.registerToSwipeEvents(this);
and then Implement SwipeListenerFragment.onSwipeEventDetected in it:
@Override
public void swipeLeftDetected()
Toast.makeText(getActivity(), "left", Toast.LENGTH_SHORT).show();
@Override
public void swipeRightDetected()
Toast.makeText(getActivity(), "right", Toast.LENGTH_SHORT).show();
这有点复杂,但效果很好:)
【讨论】:
【参考方案11】:我想补充已接受的答案,该答案部分有效,但缺少时间变量,这使它完美。
具有时间变量的最简单的从左到右滑动检测器:
在您的活动类中添加以下属性:
private float x1,x2;
private long startClickTime;
static final int MIN_DISTANCE = 150;
static final int MAX_SWIPE_TIME = 200;
并覆盖onTouchEvent()方法:
@Override
public boolean onTouchEvent(MotionEvent event)
switch(event.getAction())
case MotionEvent.ACTION_DOWN:
startClickTime = Calendar.getInstance().getTimeInMillis();
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
long clickDuration = Calendar.getInstance().getTimeInMillis() - startClickTime;
x2 = event.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE && clickDuration < MAX_SWIPE_TIME)
Toast.makeText(this, "left2right swipe", Toast.LENGTH_SHORT).show ();
else
// consider as something else - a screen tap for example
break;
return super.onTouchEvent(event);
【讨论】:
【参考方案12】:滑动事件是一种onTouch
事件。简单地简化@Gal Rom 的答案,只需跟踪垂直和水平增量,通过一些数学运算,您就可以确定 touchEvent 的滑动类型。 (再次,让我强调这是基于先前的答案,但简单性可能会吸引新手)。这个想法是扩展一个 OnTouchListener,检测刚刚发生的滑动(触摸)类型,并为每种类型调用特定方法。
public class SwipeListener implements View.OnTouchListener
private int min_distance = 100;
private float downX, downY, upX, upY;
View v;
@Override
public boolean onTouch(View v, MotionEvent event)
this.v = v;
switch(event.getAction()) // Check vertical and horizontal touches
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
return true;
case MotionEvent.ACTION_UP:
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
//HORIZONTAL SCROLL
if (Math.abs(deltaX) > Math.abs(deltaY))
if (Math.abs(deltaX) > min_distance)
// left or right
if (deltaX < 0)
this.onLeftToRightSwipe();
return true;
if (deltaX > 0)
this.onRightToLeftSwipe();
return true;
else
//not long enough swipe...
return false;
//VERTICAL SCROLL
else
if (Math.abs(deltaY) > min_distance)
// top or down
if (deltaY < 0)
this.onTopToBottomSwipe();
return true;
if (deltaY > 0)
this.onBottomToTopSwipe();
return true;
else
//not long enough swipe...
return false;
return false;
return false;
public void onLeftToRightSwipe()
Toast.makeText(v.getContext(),"left to right",
Toast.LENGTH_SHORT).show();
public void onRightToLeftSwipe()
Toast.makeText(v.getContext(),"right to left",
Toast.LENGTH_SHORT).show();
public void onTopToBottomSwipe()
Toast.makeText(v.getContext(),"top to bottom",
Toast.LENGTH_SHORT).show();
public void onBottomToTopSwipe()
Toast.makeText(v.getContext(),"bottom to top",
Toast.LENGTH_SHORT).show();
【讨论】:
【参考方案13】:从左到右和从右到左的滑动检测器
首先,声明两个浮点数据类型的变量。
private float x1, x2;
其次,在 java 中连接你的 xml 视图。就像我有ImageView
ImageView img = (ImageView) findViewById(R.id.imageView);
第三,setOnTouchListener
在您的ImageView
上。
img.setOnTouchListener(
new View.OnTouchListener()
@Override
public boolean onTouch(View v, MotionEvent event)
// TODO Auto-generated method stub
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
x2 = event.getX();
float deltaX = x2 - x1;
if (deltaX < 0)
Toast.makeText(MainActivity.this,
"Right to Left swipe",
Toast.LENGTH_SHORT).show();
else if(deltaX >0)
Toast.makeText(MainActivity.this,
"Left to Right swipe",
Toast.LENGTH_SHORT).show();
break;
return false;
);
【讨论】:
【参考方案14】:我编写了一个简单的类,可以轻松检测滑动事件 - TOP、RIGHT、BOTTOM、LEFT。
1:检测单次滑动事件
// Detect and consume specific events
// Available methods - detectTop, detectRight, detectBottom, detectLeft
SwipeEvents.detectTop(swipeElement, new SwipeEvents.SwipeSingleCallback()
@Override
public void onSwipe()
showToast("Swiped - detectTop");
);
2:通过一个回调检测任何滑动事件。
SwipeEvents.detect( swipeElement, new SwipeEvents.SwipeCallback()
@Override
public void onSwipeTop()
//Swiped top
@Override
public void onSwipeRight()
//Swiped right
@Override
public void onSwipeBottom()
//Swiped bottom
@Override
public void onSwipeLeft()
//Swiped left
);
这里是一篇博文,里面有关于如何使用的解释:http://bmutinda.com/android-detect-swipe-events/
我还为此处提供的代码 sn-ps 创建了 Gist:https://gist.github.com/bmutinda/9578f70f1df9bd0687b8
谢谢。
【讨论】:
终极版,感谢分享这些知识。【参考方案15】:这是我使用的一个可爱的类 (如果我想在 View 上捕获事件,如果它是 ViewGroup,我使用第二个实现):
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
public class SwipeDetector implements View.OnTouchListener
private int min_distance = 100;
private float downX, downY, upX, upY;
private View v;
private onSwipeEvent swipeEventListener;
public SwipeDetector(View v)
this.v=v;
v.setOnTouchListener(this);
public void setOnSwipeListener(onSwipeEvent listener)
try
swipeEventListener=listener;
catch(ClassCastException e)
Log.e("ClassCastException","please pass SwipeDetector.onSwipeEvent Interface instance",e);
public void onRightToLeftSwipe()
if(swipeEventListener!=null)
swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.RIGHT_TO_LEFT);
else
Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
public void onLeftToRightSwipe()
if(swipeEventListener!=null)
swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.LEFT_TO_RIGHT);
else
Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
public void onTopToBottomSwipe()
if(swipeEventListener!=null)
swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.TOP_TO_BOTTOM);
else
Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
public void onBottomToTopSwipe()
if(swipeEventListener!=null)
swipeEventListener.SwipeEventDetected(v,SwipeTypeEnum.BOTTOM_TO_TOP);
else
Log.e("SwipeDetector error","please pass SwipeDetector.onSwipeEvent Interface instance");
public boolean onTouch(View v, MotionEvent event)
switch(event.getAction())
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
return true;
case MotionEvent.ACTION_UP:
upX = event.getX();
upY = event.getY();
float deltaX = downX - upX;
float deltaY = downY - upY;
//HORIZONTAL SCROLL
if(Math.abs(deltaX) > Math.abs(deltaY))
if(Math.abs(deltaX) > min_distance)
// left or right
if(deltaX < 0)
this.onLeftToRightSwipe();
return true;
if(deltaX > 0)
this.onRightToLeftSwipe();
return true;
else
//not long enough swipe...
return false;
//VERTICAL SCROLL
else
if(Math.abs(deltaY) > min_distance)
// top or down
if(deltaY < 0)
this.onTopToBottomSwipe();
return true;
if(deltaY > 0)
this.onBottomToTopSwipe();
return true;
else
//not long enough swipe...
return false;
return true;
return false;
public interface onSwipeEvent
public void SwipeEventDetected(View v, SwipeTypeEnum SwipeType);
public SwipeDetector setMinDistanceInPixels(int min_distance)
this.min_distance=min_distance;
return this;
public enum SwipeTypeEnum
RIGHT_TO_LEFT,LEFT_TO_RIGHT,TOP_TO_BOTTOM,BOTTOM_TO_TOP
这是一个使用示例:
filters_container=(RelativeLayout)root.findViewById(R.id.filters_container);
new SwipeDetector(filters_container).setOnSwipeListener(new SwipeDetector.onSwipeEvent()
@Override
public void SwipeEventDetected(View v, SwipeDetector.SwipeTypeEnum swipeType)
if(swipeType==SwipeDetector.SwipeTypeEnum.LEFT_TO_RIGHT)
getActivity().onBackPressed();
);
在某些情况下,您希望检测容器上的滑动手势并将触摸事件传递给子项,因此在这种情况下,您可以创建一个自定义视图组,比如说 RelativeLayout 并覆盖 onInterceptTouchEvent ,然后您就可以检测到滑动事件不会阻止触摸事件传递给您的子视图,例如:
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.RelativeLayout;
public class SwipeDetectRelativeLayout extends RelativeLayout
private float x1,x2;
static final int MIN_DISTANCE=150;
private onSwipeEventDetected mSwipeDetectedListener;
public SwipeDetectRelativeLayout(Context context)
super(context);
public SwipeDetectRelativeLayout(Context context, AttributeSet attrs)
super(context, attrs);
public SwipeDetectRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr)
super(context, attrs, defStyleAttr);
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
switch(ev.getAction())
case MotionEvent.ACTION_DOWN:
x1 = ev.getX();
break;
case MotionEvent.ACTION_UP:
x2 = ev.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE)
//swiping right to left
if(deltaX<0)
if(mSwipeDetectedListener!=null)
mSwipeDetectedListener.swipeEventDetected();
break;
return super.onInterceptTouchEvent(ev);
public interface onSwipeEventDetected
public void swipeEventDetected();
public void registerToSwipeEvents(onSwipeEventDetected listener)
this.mSwipeDetectedListener=listener;
【讨论】:
出色的实现,我使用了第一个选项,还添加了对 onTouch 的支持,所以我已经涵盖了 next previous 和 onTouch,谢谢! @Gal Rom 第二种方法怎么用? 优秀的答案!它绝对是用很少的努力和超级有效的。 很棒的实现。 对我来说,即使我垂直滑动也会产生不正确的 SWIPE_LEFT、SWIPE_RIGHT 事件!! (我已将 SwipeDetector 附加到我的回收视图中)。也让我的回收视图在垂直滚动时变得迟缓!【参考方案16】:public class TransferMarket extends Activity
float x1,x2;
float y1, y2;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_transfer_market);
// onTouchEvent () method gets called when User performs any touch event on screen
// Method to handle touch event like left to right swap and right to left swap
public boolean onTouchEvent(MotionEvent touchevent)
switch (touchevent.getAction())
// when user first touches the screen we get x and y coordinate
case MotionEvent.ACTION_DOWN:
x1 = touchevent.getX();
y1 = touchevent.getY();
break;
case MotionEvent.ACTION_UP:
x2 = touchevent.getX();
y2 = touchevent.getY();
//if left to right sweep event on screen
if (x1 < x2)
Toast.makeText(this, "Left to Right Swap Performed", Toast.LENGTH_LONG).show();
// if right to left sweep event on screen
if (x1 > x2)
Toast.makeText(this, "Right to Left Swap Performed", Toast.LENGTH_LONG).show();
// if UP to Down sweep event on screen
if (y1 < y2)
Toast.makeText(this, "UP to Down Swap Performed", Toast.LENGTH_LONG).show();
//if Down to UP sweep event on screen
if (y1 > y2)
Toast.makeText(this, "Down to UP Swap Performed", Toast.LENGTH_LONG).show();
break;
return false;
【讨论】:
仅使用 x 坐标,从左到右,反之亦然【参考方案17】:我喜欢来自@user2999943 的代码。但只是出于我自己的目的进行了一些小的更改。
@Override
public boolean onTouchEvent(MotionEvent event)
switch(event.getAction())
case MotionEvent.ACTION_DOWN:
x1 = event.getX();
break;
case MotionEvent.ACTION_UP:
x2 = event.getX();
float deltaX = x2 - x1;
if (Math.abs(deltaX) > MIN_DISTANCE)
// Left to Right swipe action
if (x2 > x1)
Toast.makeText(this, "Left to Right swipe [Next]", Toast.LENGTH_SHORT).show ();
// Right to left swipe action
else
Toast.makeText(this, "Right to Left swipe [Previous]", Toast.LENGTH_SHORT).show ();
else
// consider as something else - a screen tap for example
break;
return super.onTouchEvent(event);
【讨论】:
嘿嘿,好像这段代码在一个带有ScrollView的activity中时,它不起作用。知道为什么吗?否则很棒的代码 Jona,同一个视图必须能够拾取 ACTION_DOWN 和 ACTION_UP 事件才能正常工作。 @AlWang 你是什么意思? 似乎在 Jona 的情况下,ScrollView 正在拦截 MotionEvent。您应该查看***.com/questions/12884250/… 的实现。 你能告诉我如何检测上下滑动吗以上是关于如何在 Android 中检测向左或向右滑动?的主要内容,如果未能解决你的问题,请参考以下文章
检测用户何时向左或向右滑动以在 WKWebView 上前后移动