I mean, I can perform the two actions sequentially but in the middle there is an ACTION_UP
MotionEvent where I removed the OnTouchListener I'm using on the view
In my case I need to avoid trigger that event.
I have a sport field with players, one of the Use Cases is move a player after a longClick, the feature works well but I can’t reproduce the feature in the tests.
Here is the code of the class I want to test, I tried to condensed all the relevant code associated to the question.
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;
}
}
Here is the test
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])));
}
}
I always use the ViewActions of the framework or use a recipe from another person changing some things but I never tried to build a complex ViewAction and I'm a bit lost.
I have seen your comments under my question. Indeed I have faced the same problem at the moment (with INJECT_EVENTS permission and all my workarounds couldn't handle it). I used that code over half year ago and it worked for me without any problems.
I can propose other solution for you but I am not 100% sure it will work. Because I have created it like super fast now. I might have more time to look at it later.
Yet try this solution:
Try to write your own GeneralSwipeAction. Look at constructor:
So position of x,y of start/end point are sent via CoordinatesProvider class. And it is an interface that returns array of floats. First float in array represent x and second one represent y.
Create your own class implementing Coordinates provider:
Implement your custom ViewAction that performs drag with usage of this CustomisableCoordinatesProvider:
And try to use it like this:
I haven't tested it. But it might work or help you by pointing to right direction. Try it and tell me if it works, I am curious myself :)