使用OnSwipeTouchListener制作字母L.

时间:2017-01-20 12:55:56

标签: android swipe gesture

我在互联网上找到了一个很好的监听器类来制作一个OnSwipeTouchListener。该监听器可以确定用户何时向下,向上,向左或向右滑动:

std::function<void(int&)>

这就是我使用它的方式:

std::function<void(int&)> myFunction = [](int& x) { ++x; };
foo(myFunction);

现在,我想添加函数onSwipeL()。此功能是当用户用手指制作字母L时,就像onSwipeDown()+ onSwipeRight()。

最好的方法是使用onSwipeDoubleL()函数。这是当用户用手指翻转双L时。它就像制作一样:

  • onSwipeDown()+ onSwipeRight()
  • onSwipeDown()+ onSwipeLeft()

这可能吗?

2 个答案:

答案 0 :(得分:0)

有两种选择。

  • 首先 - 使用一些布尔人。 isSwipedRight(例如)。如果N为真,请检查onSwipeRight(),如果是,则执行操作。在isSwipedDown中将布尔值设置为true,在所有其他值(不包括向下)中设置为false。
  • 创建自己的onTouchListener并自行测量距离。

答案 1 :(得分:0)

我真的无法理解为什么你需要这个姿势。但这是我的解决方案。我们应该捕获触摸事件,因此覆盖onTouchEvent方法。我们需要在屏幕上阅读手指索引。

如果我们有多个触摸应用右手指数,其中X坐标超过&#34;左手指&#34;。如果找到正确的索引,我无法说出来。所以我检查索引坐标。

在下一步中,我们保存起点并开始向下移动。如果我们在屏幕上有两个手指,则只检查左右手指(或者你想要的右手)。

如果我们在&#34; down&#34;距离大于最小值,我们开始向左/右移动,我们需要保存新的起点以便从中计算距离。

等待用户向左/向右移动距离超过分钟。毕竟通过&#34; left&#34;检查成功和&#34;对&#34;手指或刚刚离开(一触)。

我们还需要考虑移动时的不准确性(错误,错误)。用户无法向下移动或完全正确,因此解决方案高度依赖于此参数。您必须平衡范围和精度参数以舒适手势控制。

代码未优化仅显示基本思路。也许你会找到更多的小解决方案。对不起我的英语水平

public class MainMenuActivity extends AppCompatActivity {

    boolean movingDownL = false;
    boolean movingDownR = false;
    boolean movingLeft = false;
    boolean movingRight = false;

    boolean movingSuccessL = false;
    boolean movingSuccessR = false;

    // Deviation in pixels from the route (error value)
    int downInaccuracy = 30; // Down
    int lnrInaccuracy = 10; // Left and Right

    // Minimum distance to apply move (300 px in down and 100 to the left/right)
    int downMinDistance = 300;
    int lnrMinDistance = 50;

    Point oldCoordsL = new Point(0, 0); // Old coordinates left
    Point oldCoordsR = new Point(0, 0); // Old coordinates right
    Point startPointL = new Point(0, 0);
    Point startPointR = new Point(0, 0);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_menu);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int pIndexL = event.findPointerIndex(event.getPointerId(0));
        int pIndexR = 0;

        // If we have more than 1 touch read second finger index
        if(event.getPointerCount() > 1) pIndexR = event.findPointerIndex(event.getPointerId(1));

        // Check if we do not mistake when read fingers id
        if(event.getPointerCount() > 1 && event.getX(pIndexL) > event.getX(pIndexR)) {
            int tmp = pIndexR;
            pIndexR = pIndexL;
            pIndexL = tmp;
        }

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                movingDownL = true; // Start moving fingers
                movingDownR = true;
                movingSuccessL = false;
                movingSuccessR = false;

                // Get start point left and right if we need
                if(event.getPointerCount() > 1) {
                    startPointR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR));
                    oldCoordsR = new Point((int) event.getX(pIndexR), (int) event.getY(pIndexR));
                }

                startPointL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL));
                oldCoordsL = new Point((int) event.getX(pIndexL), (int) event.getY(pIndexL));
                break;
            case MotionEvent.ACTION_MOVE:
                // Add right finger handler
                if(event.getPointerCount() > 1) {
                    if(!movingDownR) {
                        // Check if we still moving to down
                        if(Math.abs(oldCoordsR.x - event.getX(pIndexR)) < downInaccuracy &&
                                oldCoordsR.y < event.getY(pIndexR)) break;
                        // Start moving to the right
                        if(Math.abs(oldCoordsR.y - event.getY(pIndexR)) < lnrInaccuracy &&
                                oldCoordsR.x > event.getX(pIndexR) && !movingRight) {
                            movingRight = true;
                            startPointR = new Point(new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR)));
                        }
                    }else {
                        if (Math.abs(oldCoordsR.x - event.getX(pIndexR)) > downInaccuracy ||
                                oldCoordsR.y < event.getY(pIndexR)) {
                            movingDownR = false;
                            break;
                        } else if(findDistance(startPointR,
                                new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= downMinDistance){
                            // Start moving to the left/right
                            movingDownR = false;
                        }
                    }
                }

                // Left finger handler by default even if we got only one touch
                // Check if we need move to any side
                if(!movingDownL) {
                    // Check if we still moving to down
                    if(Math.abs(oldCoordsL.x - event.getX(pIndexL)) < downInaccuracy &&
                            oldCoordsL.y < event.getY(pIndexL)) break;
                    // Start moving to the left
                    if(Math.abs(oldCoordsL.y - event.getY(pIndexL)) < lnrInaccuracy &&
                            oldCoordsL.x < event.getX(pIndexL) && !movingLeft) {
                        movingLeft = true;
                        startPointL = new Point(new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL)));
                    }
                }else {
                    if (Math.abs(oldCoordsL.x - event.getX(pIndexL)) > downInaccuracy ||
                            oldCoordsL.y > event.getY(pIndexL)) {
                        movingDownL = false;
                        break;
                    } else if(findDistance(startPointL,
                            new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= downMinDistance){
                        // Start moving to the left/right
                        movingDownL = false;
                    }
                }

                // Left move handler
                if(movingLeft) {
                    if (Math.abs(oldCoordsL.y - event.getY(pIndexL)) > lnrInaccuracy ||
                            oldCoordsL.x > event.getX(pIndexL)) {
                        movingLeft = false;
                        break;
                    } else if(findDistance(startPointL,
                            new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL))) >= lnrMinDistance) {
                        movingLeft = false;
                        movingSuccessL = true; // L from left finger is OK
                    }
                }

                // Right move handler
                if(movingRight) {
                    if (Math.abs(oldCoordsR.y - event.getY(pIndexR)) > lnrInaccuracy ||
                            oldCoordsR.x < event.getX(pIndexR)) {
                        movingRight = false;
                        break;
                    } else if(findDistance(startPointR,
                            new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR))) >= lnrMinDistance) {
                        movingRight = false;
                        movingSuccessR = true; // L from right finger is OK
                    }
                }

                if(movingSuccessL && movingSuccessR) {
                    Toast.makeText(this, "Yeah, it's look like double L", Toast.LENGTH_SHORT).show();
                } else if(movingSuccessL) Toast.makeText(this, "Yeah, it's look like L", Toast.LENGTH_SHORT).show();

                oldCoordsL = new Point((int)event.getX(pIndexL), (int)event.getY(pIndexL));
                oldCoordsR = new Point((int)event.getX(pIndexR), (int)event.getY(pIndexR));

                break;
            case MotionEvent.ACTION_UP:
                movingDownL = false;
                movingDownR = false;
                movingLeft = false;
                movingRight = false;
                break;
            default:
                return false;
        }

        return true;
    }

    private double findDistance(Point p1, Point p2) {
        return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
    }
}