From a look at the source of TouchUtils, the problem is that the number of steps is just the number of touch events to generate and does not affect how quickly they occur:
for (int i = 0; i < stepCount; ++i) { y += yStep; x += xStep; eventTime = SystemClock.uptimeMillis(); event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0); inst.sendPointerSync(event); inst.waitForIdleSync(); }
It waits for synchronization with the application after each event, so it does not seem to be happening fast enough to run. We can see that from how the GestureDetector recognizes a throw:
// A fling must travel the minimum tap distance final VelocityTracker velocityTracker = mVelocityTracker; velocityTracker.computeCurrentVelocity(1000); final float velocityY = velocityTracker.getYVelocity(); final float velocityX = velocityTracker.getXVelocity(); if ((Math.abs(velocityY) > ViewConfiguration.getMinimumFlingVelocity()) || (Math.abs(velocityX) > ViewConfiguration.getMinimumFlingVelocity())){ handled = mListener.onFling(mCurrentDownEvent, mCurrentUpEvent, velocityX, velocityY); }
Therefore, I recommend a custom drag-and-drop method that does not wait for synchronization with every touch move event (we donβt care that the user interface is updated with every drag and drop movement anyway, we just want to generate a transfer). Something like this (not verified):
public static void fling(InstrumentationTestCase test, float fromX, float toX, float fromY, float toY, int stepCount) { Instrumentation inst = test.getInstrumentation(); long downTime = SystemClock.uptimeMillis(); long eventTime = SystemClock.uptimeMillis(); float y = fromY; float x = fromX; float yStep = (toY - fromY) / stepCount; float xStep = (toX - fromX) / stepCount; MotionEvent event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, fromX, y, 0); inst.sendPointerSync(event); inst.waitForIdleSync(); for (int i = 0; i < stepCount; ++i) { y += yStep; x += xStep; eventTime = SystemClock.uptimeMillis(); event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_MOVE, x, y, 0); inst.sendPointerSync(event);
Well, in fact, all I did was comment on the expectation of waiting for unoccupied synchronization in the motion event loop. Choose some reasonable values ββfor the distance traveled and the number of steps, and this should work. If this is not the case, you may need to wait a short time in the loop to withstand events a bit if they are too fast.