如何在安卓手机上捕捉手指运动方向?

23
我希望可以在安卓手机上捕获手指移动的方向。如果用户沿着上下左右滑动手指,我需要捕获这个方向。如何找到这个方向?谢谢。

我想在安卓触摸手机上捕捉手指的移动方向。 如果用户向上/向下/向左/向右滑动手指,我希望能够捕捉这个方向。 我该如何寻找这个方向?谢谢。

3个回答

48

实现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";
        }
    }
}

4
回答不错,但我发现有些错别字,并且我需要将其中一些变量提升到更高的作用域,以便在switch语句内部使它们可变。 - Abel Tamayo
2
对于第二个switch case,我使用了ACTION_MOVE而不是ACTION_UP,因为在ViewPager中,滑动操作会在没有ACTION_UP的情况下被调用。我有一个垂直方向的ScrollView,由ViewGroup持有,并且它是ViewPager的一页。在ScrollView上滑动会改变页面,而不是不响应。case MotionEvent.ACTION_MOVE: float dx = event.getX() - x1; float dy = event.getY() - y1; if (Math.abs(dx) <= Math.abs(dy)) {//垂直滚动 v.getParent().requestDisallowInterceptTouchEvent(true); } else { v.getParent().requestDisallowInterceptTouchEvent(false); } break; - st_bk
嵌套在另一个ViewGroup中的具有垂直方向的ScrollView,我是这个意思。 - st_bk
2
如果用户抬起手指并移动手指,则此方法有效,但如果用户在不抬起手指的情况下改变方向,该如何处理? - Irfan
如何处理dx或dy将为0的情况? - vishal patel
@vishalpatel 目前它会默认为“左”和“上”,但你可以添加一个“else if”情况来处理“中心”。 - cstack

13

您最好的选择是处理从View.OnTouchListener()回调中获取的MotionEvent。运动事件通过其操作属性跟踪您当前与视图的交互方式。

我想您可以通过检查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


1
底部检查应为 if(Math.abs(deltaY)>Math.abs(deltaX)) - tibbi

2
我认为,与其使用一堆变量,不如使用VelocityTracker更好。
以下是从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
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接