java – Android Espresso,如何继续执行onLongClick和slideDown?

我的意思是,我可以按顺序执行这两个动作,但在中间有一个ACTION_UP MotionEvent,我删除了我在视图上使用的OnTouchListener

在我的情况下,我需要避免触发该事件.

我有一个运动场与玩家,其中一个用例是在longClick之后移动玩家,该功能运行良好但我无法在测试中重现该功能.

《java – Android Espresso,如何继续执行onLongClick和slideDown?》

这是我要测试的类的代码,我试图压缩与该问题相关的所有相关代码.

public class FootballFieldLayout extends RelativeLayout implements View.OnTouchListener {
    [...]
    public void addPlayer(FieldPlayer player) {
        final FieldPlayerView fpv = new FieldPlayerView(getContext(), player);
        addView(fpv);
        fpv.setOnLongClickListener(new OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                v.setOnTouchListener(FootballFieldLayout.this);
                    return true;
                }
            });
    }
    [...]
    public float dX=NO_DELTA, dY=NO_DELTA;

    @Override
    public boolean onTouch(View view, MotionEvent event) {
        switch (event.getAction()) {

            case MotionEvent.ACTION_MOVE:
                if(dX == NO_DELTA || dY == NO_DELTA){ setDelta(view, event); }
                view.animate()
                    .x(event.getRawX() + dX)
                    .y(event.getRawY() + dY)
                    .setDuration(0)
                    .start();
                    break;
            case MotionEvent.ACTION_UP:
                view.setOnTouchListener(null);
                resetDelta();
                break;
            default:
                return false;
        }
        return true;
    }
}

这是测试

public class MoveOnLongClickActivityTest {
    [...]
    @Test
    public void playerCanBeMovedVerticallyAfterLongClick() throws InterruptedException {
        onView(withId(R.id.activity_field)).check(matches(isDisplayed()));
        View view = mActivityRule.getActivity().findViewById(R.id.test_player);

        float[] beginCoord = {view.getX(), view.getY()};
        onView(withId(R.id.test_player)).perform(longClick());
        onView(withId(R.id.test_player)).perform(swipeDown());
        float[] endCoord = {view.getX(), view.getY()};

        assertThat(beginCoord[1], not(equalTo(endCoord[1])));
    }
}

我总是使用框架的ViewActions或使用来自另一个人改变某些东西的食谱,但我从未尝试过构建复杂的ViewAction而且我有点迷失.

最佳答案 我在我的问题下看到了你的意见.事实上,我目前遇到了同样的问题(使用INJECT_EVENTS权限并且我的所有变通办法都无法处理).我在半年前使用过该代码,它对我没有任何问题.

我可以为您提出其他解决方案,但我不是100%确定它会起作用.因为我现在已经像超快速创造了它.我可能有更多的时间来看待它.

尝试这个解决方案:

>尝试编写自己的GeneralSwipeAction.看一下构造函数:

public GeneralSwipeAction(Swiper swiper, CoordinatesProvider startCoordinatesProvider, CoordinatesProvider endCoordinatesProvider, PrecisionDescriber precisionDescriber) {
    this.swiper = swiper;
    this.startCoordinatesProvider = startCoordinatesProvider;
    this.endCoordinatesProvider = endCoordinatesProvider;
    this.precisionDescriber = precisionDescriber;
}

因此,开始/结束点的x,y位置通过CoordinatesProvider类发送.它是一个返回浮点数组的接口.数组中的第一个浮点数表示x,第二个浮点数表示y.

>创建自己的实现坐标提供程序的类:

import android.support.test.espresso.action.CoordinatesProvider;
import android.view.View;

public class CustomisableCoordinatesProvider implements CoordinatesProvider {

    private int x;
    private int y;

    public CustomisableCoordinatesProvider(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public float[] calculateCoordinates(View view) {
        return new float[]{x,y};
    }
}

>实现使用此CustomisableCoordinatesProvider执行拖动的自定义ViewAction:

public static ViewAction drag(int startX, int startY, int endX, int endY) {
    return new GeneralSwipeAction(
        Swipe.FAST,
        new CustomisableCoordinatesProvider(startX, startY),
        new CustomisableCoordinatesProvider(endX, endY),
        Press.FINGER);
}

>并试着像这样使用它:

onView(withId(R.id.test_player)).perform(drag(0, 100, 0, 100));

我没有测试过.但它指向正确的方向可能会起作用或帮助你.尝试一下,告诉我它是否有效,我很好奇自己:)

点赞