Android:在onTouch里实现onClick的坑

前段时间做了个需求,一个200 * 200的view要可以被拖动,点击也可以跳转。拖动的实现很自然的想到了监听view的touch事件,在move的时候设置view的位置,代码大概如下:

mDraggableView.setOnTouchListener(new View.OnTouchListener() {
            float dX;
            float dY;

            @Override
            public boolean onTouch(View view, MotionEvent event) {
                switch (event.getActionMasked()) {
                    case MotionEvent.ACTION_DOWN:
                        dX = view.getX() - event.getRawX();
                        dY = view.getY() - event.getRawY();
                        break;

                    case MotionEvent.ACTION_MOVE:
                        view.setX(event.getRawX() + dX);
                        view.setY(event.getRawY() + dY);
                        break;

                    default:
                        return false;
                }
                return true;
            }
        });

点击则在手指抬起,即ACTION_UP事件回调时实现。如果上一个回调的事件是ACTION_DOWN,则判定为click事件,而不是拖动。代码大概如下:

mDraggableView.setOnTouchListener(new View.OnTouchListener() {
            float dX;
            float dY;
            int lastAction;

            @Override
            public boolean onTouch(View view, MotionEvent event) {
                switch (event.getActionMasked()) {
                    case MotionEvent.ACTION_DOWN:
                        dX = view.getX() - event.getRawX();
                        dY = view.getY() - event.getRawY();
                        lastAction = MotionEvent.ACTION_DOWN;
                        break;

                    case MotionEvent.ACTION_MOVE:
                        view.setX(event.getRawX() + dX);
                        view.setY(event.getRawY() + dY);
                        lastAction = MotionEvent.ACTION_MOVE;
                        break;

                    case MotionEvent.ACTION_UP:
                        if (lastAction == MotionEvent.ACTION_DOWN) {
                            // click event, do something
                        }
                        break;

                    default:
                        return false;
                }
                return true;
            }
        });

在自己的开发机上测试,正常,没有问题。本以为万事大吉了,但测试却提了个bug,说点击后没效果。于是我找了台可以复现的手机,发现这些手机确实有bug,明明只是一个很明确的点击事件,手指真的一点也没动,它们却还有ACTION_MOVE事件的回调!!但是位移不大,只有一两个像素。要解决这个坑爹的问题,我们要将这种只有几个像素移动的“拖动”判定为点击事件,那就加个距离的判断吧。代码如下:

mDraggableView.setOnTouchListener(new View.OnTouchListener() {
            private static final int MIN_DISTANCE = 10;
            float initialX;
            float initialY;

            float dX;
            float dY;
            int lastAction;
            boolean farEnough = false;

            @Override
            public boolean onTouch(View view, MotionEvent event) {
                switch (event.getActionMasked()) {
                    case MotionEvent.ACTION_DOWN:
                        initialX = event.getRawX();
                        initialY = event.getRawY();
                        dX = view.getX() - event.getRawX();
                        dY = view.getY() - event.getRawY();
                        lastAction = MotionEvent.ACTION_DOWN;
                        break;

                    case MotionEvent.ACTION_MOVE:
                        if (!farEnough) {
                            if (Math.abs(event.getRawX() - initialX) > MIN_DISTANCE
                                || Math.abs(event.getRawY() - initialY) > MIN_DISTANCE) {
                                farEnough = true;
                            }
                        }
                        view.setX(event.getRawX() + dX);
                        view.setY(event.getRawY() + dY);
                        lastAction = MotionEvent.ACTION_MOVE;
                        break;

                    case MotionEvent.ACTION_UP:
                        if (lastAction == MotionEvent.ACTION_DOWN
                            || (lastAction == MotionEvent.ACTION_MOVE && !farEnough)) {
                            // click event, do something
                        }
                        farEnough = false;
                        break;

                    default:
                        return false;
                }
                return true;
            }
        });

 

你可能感兴趣的:(Android)