【问题标题】:How to capture finger movement direction in android phone?如何在安卓手机中捕捉手指运动方向?
【发布时间】:2020-04-29 23:05:54
【问题描述】:

我想在 Android 触控手机上捕捉手指的移动方向。如果用户在上/下/左/右方向滑动手指,我想捕捉这个方向。我怎样才能找到这个?谢谢。

【问题讨论】:

    标签: android


    【解决方案1】:

    实现onTouchEvent(),根据用户按下和抬起的位置计算dx和dy。您可以使用这些值来确定移动的方向。

    float x1, x2, y1, y2, dx, dy;
    String direction;
    switch(event.getAction()) {
        case(MotionEvent.ACTION_DOWN):
            x1 = event.getX();
            y1 = event.getY();
            break;
    
        case(MotionEvent.ACTION_UP): {
            x2 = event.getX();
            y2 = event.getY();
            dx = x2-x1;
            dy = y2-y1;
    
            // Use dx and dy to determine the direction of the move
            if(Math.abs(dx) > Math.abs(dy)) {
                if(dx>0)
                  direction = "right";
                else
                  direction = "left";
            } else {
                if(dy>0)
                  direction = "down";
                else
                  direction = "up";
            }
        }
    }
    

    【讨论】:

    • 很好的答案,但我发现了一些拼写错误,不得不将其中一些变量带到更高的范围,以使它们在开关内部可变。
    • 对于第二个 switch 案例,我使用了 ACTION_MOVE 而不是 ACTION_UP,因为在 ViewPager 中滑动被调用而没有 ACTION_UP。我有一个由 ViewGroup 持有的带有垂直方向的 ScrollView,这是一个 ViewPager 页面。在 ScrollView 上滑动确实会更改页面而不是不响应。 case MotionEvent.ACTION_MOVE: float dx = event.getX() - x1; float dy = event.getY() - y1;if (Math.abs(dx)
    • ScrollView w/ 垂直方向嵌套在另一个 ScrollView 中,由我的意思的 ViewGroup 持有。
    • 如果用户抬起手指并移动手指,这个效果很好,如果用户改变方向而不抬起手指,如何处理?
    • 当dx或dy为0时如何处理?
    【解决方案2】:

    最好的办法是处理从 View.OnTouchListener() 回调中获得的 MotionEvent。运动事件通过其 action 属性跟踪您当前与 View 的交互方式。

    我想你可以通过检查 MotionEvents 的动作属性和运动事件发生位置的 x/y 值来计算某人滑动手指的方向。

    switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                oldX= event.getX();
                oldY= event.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                int newX = motionEvent.getX();
                int newY = motionEvent.getY();
    
                int deltaX = oldX - newX;
                int deltaY = oldY - newY;
    
                if(Math.abs(deltaY)>Math.abs(deltaX))
                  //Motion in Y direction.
                else
                  // Motion in X direction.
                break;
             }
    

    MotionEvent 对象上还有许多其他方法可供使用: http://developer.android.com/reference/android/view/MotionEvent.html

    【讨论】:

    • 底部检查应该是if(Math.abs(deltaY)>Math.abs(deltaX))
    【解决方案3】:

    我认为使用VelocityTracker而不是使用一堆变量更好

    这是来自Developer Android的修改示例

    private var mVelocityTracker: VelocityTracker? = null
    
    override fun onTouchEvent(event: MotionEvent): Boolean {
    
        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                // Reset the velocity tracker back to its initial state.
                mVelocityTracker?.clear()
                // If necessary retrieve a new VelocityTracker object to watch the
                // velocity of a motion.
                mVelocityTracker = mVelocityTracker ?: VelocityTracker.obtain()
                // Add a user's movement to the tracker.
                mVelocityTracker?.addMovement(event)
            }
            MotionEvent.ACTION_MOVE -> {
                mVelocityTracker?.run {
                    val pointerId: Int = event.getPointerId(event.actionIndex)
                    addMovement(event)
                    // When you want to determine the velocity, call
                    // computeCurrentVelocity(). Then call getXVelocity()
                    // and getYVelocity() to retrieve the velocity for each pointer ID.
                    computeCurrentVelocity(1000)
    
                    val xVelocity = getXVelocity(pointerId)
                    val yVelocity = getYVelocity(pointerId)
    
                    if (abs(xVelocity) > abs(yVelocity))
                        if (xVelocity > 0)
                            // right
                        else
                            // left 
                    else
                        if (yVelocity > 0)
                           // down
                        else
                           // up
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                // Return a VelocityTracker object back to be re-used by others.
                mVelocityTracker?.recycle()
                mVelocityTracker = null
            }
        }
        return true
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多