【问题标题】:How to detect the swipe left or Right in Android?如何在 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;
    }
}

【问题讨论】:

标签: android android-layout android-edittext


【解决方案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_width="match_parent"
                  android:id="@+id/main_list_layout"
                  android:clickable="true"
                  android:focusable="true"
                  android:focusableInTouchMode="true"
                  android:layout_height="match_parent" 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_width="match_parent"
                      android:layout_height="match_parent"
                      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。您应该查看stackoverflow.com/questions/12884250/… 的实现。
                      • 你能告诉我如何检测上下滑动吗
                      猜你喜欢
                      • 2011-07-23
                      • 2011-03-29
                      • 1970-01-01
                      • 2018-02-05
                      • 2022-11-23
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2020-01-29
                      相关资源
                      最近更新 更多