最适合我的解决方案是在 OnTouchListener 中传递 MotionEvent 在 ViewPager 实例之间。尝试过假拖动,但它总是很慢而且有问题(也尝试了这个线程的解决方案 - 没用) - 我需要一个平滑的、类似视差的效果。
所以,我的建议是实现View.OnTouchListener。 MotionEvent 必须进行缩放以补偿宽度差异。
public class SyncScrollOnTouchListener implements View.OnTouchListener {
private final View syncedView;
public SyncScrollOnTouchListener(@NonNull View syncedView) {
this.syncedView = syncedView;
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
MotionEvent syncEvent = MotionEvent.obtain(motionEvent);
float width1 = view.getWidth();
float width2 = syncedView.getWidth();
//sync motion of two view pagers by simulating a touch event
//offset by its X position, and scaled by width ratio
syncEvent.setLocation(syncedView.getX() + motionEvent.getX() * width2 / width1,
motionEvent.getY());
syncedView.onTouchEvent(syncEvent);
return false;
}
}
然后将其设置为您的ViewPager
sourcePager.setOnTouchListener(new SyncScrollOnTouchListener(targetPager));
请注意,此解决方案仅在两个寻呼机具有相同方向时才有效。如果您需要它适用于不同的方向 - 调整 syncEvent Y 坐标而不是 X。
我们还需要考虑一个问题 - 最小的投掷速度和距离,这可能会导致只有一个寻呼机改变页面。
可以通过在我们的寻呼机中添加OnPageChangeListener 轻松解决此问题
sourcePager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
//no-op
}
@Override
public void onPageSelected(int position) {
targetPager.setCurrentItem(position, true);
}
@Override
public void onPageScrollStateChanged(int state) {
//no-op
}
});