如何在 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()
    

您可以在 ActivityFragment 中轻松实现它。

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 上前后移动

向左或向右滑动时,我的卡片视图不会总是消失?

在 UITableViewCell 中的任意位置向左或向右滑动以删除没有删除按钮的单元格?

你可以检测到向上滑动Android头部通知

iPhone:如何向左或向右旋转 UIImageview?

如何仅在一只耳朵中播放声音 i.s.使用音频单元一次向左或向右