【问题标题】:How can I perform a multi touch swipe with Espresso?如何使用 Espresso 执行多点触控滑动?
【发布时间】:2015-03-13 13:45:28
【问题描述】:

如何使用 Espresso 执行多点触控滑动?例如两指向右滑动。

【问题讨论】:

    标签: testing android-espresso gui-testing ui-testing


    【解决方案1】:

    正如@Daniel 建议的那样,我创建了一个自定义版本的 MotionEvents,因为当使用多个手指时,您必须注入 ACTION_POINTER_DOWN/UP 而不是 ACTION_DOWN/UP。 我创建了一个双指版本的 LinearSwipe,如下所示:

    private static Swiper.Status sendLinearSwipe(UiController uiController,
                                                 float[] startCoordinates,
                                                 float[] startCoordinatesSecondFinger,
                                                 float[] endCoordinates,
                                                 float[]endCoordinatesSecondFinger,
                                                 float[] precision,
                                                 float[] precisionSecond,
                                                 int duration) {
        checkNotNull(uiController);
        checkNotNull(startCoordinates);
        checkNotNull(startCoordinatesSecondFinger);
        checkNotNull(endCoordinates);
        checkNotNull(endCoordinatesSecondFinger);
        checkNotNull(precision);
        checkNotNull(precisionSecond);
    
        float[][] steps = interpolate(startCoordinates, endCoordinates, SWIPE_EVENT_COUNT);
        float[][] stepsSecondFinger = interpolate(startCoordinatesSecondFinger, endCoordinatesSecondFinger, SWIPE_EVENT_COUNT);
        final int delayBetweenMovements = duration / steps.length;
        final int delayBetweenMovementsSecondFinger = duration / stepsSecondFinger.length;
    
        int maxLength=Math.min(steps.length, stepsSecondFinger.length);
    
        MotionEvent downEvent;
        downEvent = MotionEvents.sendDown(uiController, steps[0], precision,true).down;
        MotionEvent downEventSecondFinger;
        downEventSecondFinger = MotionEvents.sendDown(uiController,stepsSecondFinger[0], precisionSecond,false).down;
    
        try {
            for (int i = 1; i < maxLength; i++) {
    
                if (sendMovement(uiController, steps[i], downEvent)) return Status.FAILURE;
                if (sendMovement(uiController, stepsSecondFinger[i], downEventSecondFinger)) return Status.FAILURE;
    
    
                long desiredTime = downEvent.getDownTime() + delayBetweenMovements * i;
                long desiredTimeSecondFinger = downEventSecondFinger.getDownTime() + delayBetweenMovementsSecondFinger * i;
    
                long timeUntilDesired = desiredTime - SystemClock.uptimeMillis();
                long timeUntilDesiredSecondFinger = desiredTimeSecondFinger - SystemClock.uptimeMillis();
                loopMainThread(uiController, timeUntilDesired);
                loopMainThread(uiController, timeUntilDesiredSecondFinger);
    
            }
    
            if (!MotionEvents.sendUp(uiController, downEventSecondFinger, endCoordinatesSecondFinger,false)) {
                Log.e(TAG, "Injection of up event as part of the swipe failed. Sending cancel event.");
                MotionEvents.sendCancel(uiController, downEventSecondFinger);
                return Swiper.Status.FAILURE;
            }
        } finally {
            downEvent.recycle();
            downEventSecondFinger.recycle();
        }
        return Swiper.Status.SUCCESS;
    }
    
    private static void loopMainThread(UiController uiController, long timeUntilDesired) {
        if (timeUntilDesired > 10) {
            uiController.loopMainThreadForAtLeast(timeUntilDesired);
        }
    }
    
    private static boolean sendMovement(UiController uiController, float[] step, MotionEvent downEvent) {
        if (!MotionEvents.sendMovement(uiController, downEvent, step)) {
            Log.e(TAG, "Injection of move event as part of the swipe failed. Sending cancel event.");
            MotionEvents.sendCancel(uiController, downEvent);
            return true;
        }
        return false;
    }
    

    现在完美运行!谢谢@丹尼尔

    【讨论】:

    • 能否在示例中也包含 interpolate 方法?
    【解决方案2】:

    Espresso 不提供该功能,但您可以自己完成

    • 注入两个向下事件
    • 注入几对运动事件,每个手指一个
    • 注入两个向上事件

    Espresso 有一些实用程序可以让您更轻松地进行操作。特别是,MotionEvents 类有一些帮助方法来创建和注入这些低级事件。

    您可能需要参考sendLinearSwipe 代码,其中包含单点触摸滑动的大部分逻辑。

    如果您将其写为ViewAction,它将完全适合 Espresso 框架(例如,您可以轻松地让它等待空闲资源)。

    【讨论】:

    • 谢谢,我现在可以使用它了。但是,当我注入两个向上事件时它会失败。但是,如果我只注入一个向上事件,它就可以正常工作:)
    猜你喜欢
    • 1970-01-01
    • 2022-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多