我的意思是,我可以按顺序执行这两个动作,但是在中间有一个ACTION_UP
MotionEvent我删除了我在视图上使用的OnTouchListener
在我的情况下,我需要避免触发该事件。
我有一个带有玩家的运动场,其中一个用例是在longClick之后移动玩家,该功能运行良好,但我无法在测试中重现该功能。
以下是我要测试的类的代码,我试图压缩与该问题相关的所有相关代码。
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而且我有点迷失。
答案 0 :(得分:2)
我已经在我的问题下看到了你的意见。事实上,我目前遇到了同样的问题(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));
我还没有测试过它。但它指向正确的方向可能会起作用或帮助你。尝试一下,告诉我它是否有效,我很好奇自己:)