我正在使用VelocityViewPager found in this post来实现可移动的ViewPager。我试图通过在VelocityViewPager(1970年代)中间显示一个元素来设置视图寻呼机进行初始化。所以在我的片段的onViewCreated()中我做了:
velocityViewPager.setCurrentItem(69);
用户建议执行以下操作以在post的评论中解决此问题:
private void trackMotion(float distX) {
final int width = getWidth();
final int widthWithMargin = width + this.getPageMargin();
float scrollOffset = getScrollX() - (this.getCurrentItem() * widthWithMargin);
float scrollX = getScrollX() - distX - scrollOffset;
........
}
然而,当我尝试这个时,它不起作用,我会被看到ViewPager的元素68,69和70,因为scrollX会被卡住,因为偏移会锁定" scrollX到范围。
我注意到的问题是当scrollX真正应该是表示位置69的值时,它被初始化为0.我尝试在XML中手动设置scrollX,在Java代码中设置scrollX,并进行各种偏移计算无济于事。
答案 0 :(得分:1)
这就是我最终为一个可观的观点所做的事情。这肯定更痛苦(我需要大量的试验和错误)而不仅仅是从视图寻呼机扩展,但它给了我想要的东西。您必须找到一种方法来使用View的scrollX来确定要捕捉的项目以及到达视图结束或开始时要执行的操作。
public class FlingableScroller extends View implements GestureDetector.OnGestureListener {
public FlingableScroller(Context context, AttributeSet attrs) {
super(context, attrs);
mGestureDetector = new GestureDetector(context, this);
mScroller = new OverScroller(context);
//This is how you "set current item" You will have to calculate INITIAL_SCROLL_X yourself
setScrollX(INITIAL_SCROLL_X);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
animateFlingIfApplicable();
}
private void animateFlingIfApplicable() {
//We have a fling only if computeScrollOffset is true.
if (mScroller.computeScrollOffset()) {
//Flinging passed the start point so continue the fling at the end
if (mScroller.getFinalX() == 0) {
int velocity = getFlingVelocity();
mScroller.forceFinished(true);
mScroller.fling(MAXIMUM_SCROLL_X, 0, velocity / FRICTION_COEFFICIENT, 0, 0, MAXIMUM_SCROLL_X, 0, 0);
//Flinging passed the end point so continue the fling at the start
} else if (mScroller.getFinalX() == MAXIMUM_SCROLL_X) {
int velocity = getFlingVelocity();
mScroller.forceFinished(true);
mScroller.fling(0, 0, velocity / FRICTION_COEFFICIENT, 0, 0, MAXIMUM_SCROLL_X, 0, 0);
} else if (mScroller.getFinalX() == getScrollX() || mScroller.getCurrVelocity() == 0) {
snapToItem();
mScroller.forceFinished(true);
} else {
scrollTo(mScroller.getCurrX(), 0);
}
}
invalidate();
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//This logic handles the case when you scroll pass the beginning or the end of the scroller
if (getScrollX() > MAXIMUM_SCROLL_X) {
scrollTo(0, 0);
} else if (getScrollX() >= 0) {
scrollBy(distance, 0);
} else {
scrollTo(MAXIMUM_SCROLL_X, 0);
}
invalidate();
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//This is to prevent low velocity "flings"
if (Math.abs(velocityX) < 400 * SCREEN_DENSITY) {
return false;
}
mScroller.forceFinished(true);
//Define friction_coefficient to a value that gives you desirable flinging.
mScroller.fling(getScrollX(), getScrollY(), (int) -velocityX / FRICTION_COEFFICIENT, 0, 0, MAXIMUM_SCROLL_X, 0, 0);
invalidate();
return true;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mScroller.forceFinished(true);
break;
case MotionEvent.ACTION_UP:
snapToItem();
invalidate();
break;
}
return mGestureDetector.onTouchEvent(event);
}
private void snapToItem() {
//The the user lifts up their finger from a scroll or when a fling finishes determine what item to snap to. See the ViewPager source code to emulate the "fake drag"
int scrollByValue = getScrollX() / SOME_VALUE
scrollTo(scrollByValue, 0);
}
}