Reputation: 22028
I have a ViewPager
with Fragment
s in it. I want to programmatically create a motion event to 'peek' at the Fragment
s left and right to the current Fragment
in the ViewPager
(showing part of the adjacent Fragments, then moving back to the current Fragment
). It should look like a user was doing this.
I tried ViewPager.fakeDragBy
but this happens instantly and is too fast.
I had a look at MotionEvent.obtain()
and View.dispatchTouchEvent
, this seems the way to go to do this, right?
On which View
do i have to dispatch the MotionEvents
on?
And do I have to manually dispatch several MotionEvent
s to achieve what I want, e.g. ACTION_DOWN
, ACTION_???
, ACTION_UP
?
EDIT:
I tried the following:
public void drag(View view, float fromX, float toX, float fromY,
float toY, int stepCount) {
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, x, y, 0);
view.dispatchTouchEvent(event);
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);
view.dispatchTouchEvent(event);
}
eventTime = SystemClock.uptimeMillis();
event = MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_UP, x, y, 0);
view.dispatchTouchEvent(event);
}
Which creates a drag motion just fine, problem is: it is very fast. I tried Thread.sleep()
inside the loop and playing around with the eventTime (adding some time to it on every iteration within the for-loop), to no avail: the touch events are dispatched delayed, but the actual reaction of the ViewPager
still happens very fast.
Upvotes: 4
Views: 9135
Reputation: 3705
1st way:
Use OverScroller
object with LinearInterpolator
and set a duration duration (from x1 to x2 in 300ms maybe)
call computeScrollOffset()
inside your for loop to find current position and break the loop when isFinished()
returns true.
2nd way
Use Object animator with custom property and use your fakeDrag method in it and run it like a common animation.
Upvotes: 1
Reputation: 3993
You can do:
if (!viewpager.isFakeDragging()) {
viewpager.beginFakeDrag();
}
viewpager.fakeDragBy(value);
Documentation: fakeDragBy(float), beginFakeDrag(), endFakeDrag().
and in onAnimationEnd()
@Override
public void onAnimationEnd(Animator mAnimation) {
viewpager.endFakeDrag();
}
Upvotes: 1