背景
考虑以下情况:
- 有两个viewPager,它们的宽度和高度不同,但它们都拥有完全相同数量的页面。
- 在一个viewPager上滑动应该会使另一个viewPager随之滑动,这样就像“视差”效果。
- 与#2相同,但是针对其他viewPager。
- 还有一个自动切换机制,在viewPagers之间每2秒自动切换到下一页(如果在最后一页,则切换回第一页)。
问题
我认为我已经实现了一些功能,但它有一些问题:
- 这只是简单的XML,没有什么特别的。
- 我使用了“OnPageChangeListener”,并在其中的“onPageScrolled”中使用了伪拖动。问题在于,如果用户的拖动停在页面的中心附近(从而激活自动滚动viewPager左/右),则伪拖动会失去同步,可能会出现奇怪的事情:错误的页面甚至停留在页面之间...
- 目前,我不处理用户拖动的另一个viewPager,但这也可能是一个问题。
当我解决#2(或#3)时,这可能是一个问题。目前,我使用一个处理程序,它使用可运行的方法,并调用此命令:
mViewPager.setCurrentItem((mViewPager.getCurrentItem() + 1) % mViewPager.getAdapter().getCount(), true);
我尝试过的方法
我尝试了这篇文章,但它并没有很好地工作,因为当用户拖动停止时,它会出现相同的问题,导致页面未完全切换到另一页。
唯一有效的类似解决方案是使用单个ViewPager (在这里),但我需要使用两个ViewPager,每个ViewPager都会影响另一个。
所以我尝试自己做:假设一个viewPager是“viewPager”,另一个(应该跟随“viewPager”的)是“viewPager2”,这是我做的:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
int lastPositionOffsetPixels=Integer.MIN_VALUE;
@Override
public void onPageScrolled(final int position, final float positionOffset, final int positionOffsetPixels) {
if (!viewPager2.isFakeDragging())
viewPager2.beginFakeDrag();
if(lastPositionOffsetPixels==Integer.MIN_VALUE) {
lastPositionOffsetPixels=positionOffsetPixels;
return;
}
viewPager2.fakeDragBy((lastPositionOffsetPixels - positionOffsetPixels) * viewPager2.getWidth() / viewPager.getWidth());
lastPositionOffsetPixels = positionOffsetPixels;
}
@Override
public void onPageSelected(final int position) {
if (viewPager2.isFakeDragging())
viewPager2.endFakeDrag();
viewPager2.setCurrentItem(position,true);
}
@Override
public void onPageScrollStateChanged(final int state) {
}
});
我选择使用虚拟拖动,因为即使文档也表示在这种情况下它可能非常有用:
如果您想将 ViewPager 的动作与另一个视图的触摸滚动同步,同时仍然让 ViewPager 控制捕捉动作和快速滑动的行为,则虚拟拖动可能非常有用。 (例如视差滚动标签。)调用 fakeDragBy(float) 模拟实际拖动动作。 调用 endFakeDrag() 完成虚拟拖动并根据需要进行快速滑动。
为了方便测试,这里是更多的代码:
MainActivity.java
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ViewPager viewPager = (ViewPager) findViewById(R.id.viewPager);
final ViewPager viewPager2 = (ViewPager) findViewById(R.id.viewPager2);
viewPager.setAdapter(new MyPagerAdapter());
viewPager2.setAdapter(new MyPagerAdapter());
//do here what's needed to make "viewPager2" to follow dragging on "viewPager"
}
private class MyPagerAdapter extends PagerAdapter {
int[] colors = new int[]{0xffff0000, 0xff00ff00, 0xff0000ff};
@Override
public int getCount() {
return 3;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
((ViewPager) container).removeView((View) object);
}
@Override
public boolean isViewFromObject(final View view, final Object object) {
return (view == object);
}
@Override
public Object instantiateItem(final ViewGroup container, final int position) {
TextView textView = new TextView(MainActivity.this);
textView.setText("item" + position);
textView.setBackgroundColor(colors[position]);
textView.setGravity(Gravity.CENTER);
final LayoutParams params = new LayoutParams();
params.height = LayoutParams.MATCH_PARENT;
params.width = LayoutParams.MATCH_PARENT;
params.gravity = Gravity.CENTER;
textView.setLayoutParams(params);
textView.setTextColor(0xff000000);
container.addView(textView);
return textView;
}
}
activity_main
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="viewPager:"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="viewPager2:"/>
<android.support.v4.view.ViewPager
android:id="@+id/viewPager2"
android:layout_width="match_parent"
android:layout_height="100dp"/>
</LinearLayout>
问题
这段代码基本上可以正常工作。 我只需要知道,为了避免用户停止拖动,还缺少什么内容? 其他问题可能有更简单的解决方案。