and*_*per 15 android parallax android-viewpager
请考虑以下情形:
我认为我有一些功能,但它有一些问题:
当我成功解决#2(或#3)时,这可能是一个问题.现在,我正在使用一个使用runnable的处理程序并在其中调用此命令:
mViewPager.setCurrentItem((mViewPager.getCurrentItem() + 1) % mViewPager.getAdapter().getCount(), true);
Run Code Online (Sandbox Code Playgroud)我已经尝试过这篇文章了,但是效果不好,因为当用户拖动到完成切换到另一个页面之前停止时它会出现同样的问题.
只有类似的解决方案可以使用单个ViewPager(此处),但我需要使用2个ViewPagers,每个都会影响另一个.
所以我自己尝试过:假设一个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) {
}
});
Run Code Online (Sandbox Code Playgroud)
我选择使用假拖动,因为即使文档说它对这个完全相同的场景也很有用:
如果要将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;
}
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
代码几乎运作良好.我只需要知道,缺少什么来避免停止拖动(由用户)的问题?其他问题可能有更简单的解决方案.
经过大量的工作,我们找到了几乎没有错误的解决方案.有一个罕见的错误,滚动时,另一个viewPager闪烁.奇怪的是,它只在用户滚动第二个viewPager时才会发生.所有其他尝试都有其他问题,例如在完成滚动到新页面时的空页或"跳跃"/"橡胶"效果.
这是代码:
private static class ParallaxOnPageChangeListener implements ViewPager.OnPageChangeListener {
private final AtomicReference<ViewPager> masterRef;
/**
* the viewpager that is being scrolled
*/
private ViewPager viewPager;
/**
* the viewpager that should be synced
*/
private ViewPager viewPager2;
private float lastRemainder;
private int mLastPos = -1;
public ParallaxOnPageChangeListener(ViewPager viewPager, ViewPager viewPager2, final AtomicReference<ViewPager> masterRef) {
this.viewPager = viewPager;
this.viewPager2 = viewPager2;
this.masterRef = masterRef;
}
@Override
public void onPageScrollStateChanged(int state) {
final ViewPager currentMaster = masterRef.get();
if (currentMaster == viewPager2)
return;
switch (state) {
case ViewPager.SCROLL_STATE_DRAGGING:
if (currentMaster == null)
masterRef.set(viewPager);
break;
case ViewPager.SCROLL_STATE_SETTLING:
if (mLastPos != viewPager2.getCurrentItem())
viewPager2.setCurrentItem(viewPager.getCurrentItem(), false);
break;
case ViewPager.SCROLL_STATE_IDLE:
masterRef.set(null);
viewPager2.setCurrentItem(viewPager.getCurrentItem(), false);
mLastPos = -1;
break;
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if (masterRef.get() == viewPager2)
return;
if (mLastPos == -1)
mLastPos = position;
float diffFactor = (float) viewPager2.getWidth() / this.viewPager.getWidth();
float scrollTo = this.viewPager.getScrollX() * diffFactor + lastRemainder;
int scrollToInt = scrollTo < 0 ? (int) Math.ceil(scrollTo) : (int) Math.floor(scrollTo);
lastRemainder = scrollToInt - scrollTo;
if (mLastPos != viewPager.getCurrentItem())
viewPager2.setCurrentItem(viewPager.getCurrentItem(), false);
viewPager2.scrollTo(scrollToInt, 0);
}
@Override
public void onPageSelected(int position) {
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
/**the current master viewPager*/
AtomicReference<ViewPager> masterRef = new AtomicReference<>();
viewPager.addOnPageChangeListener(new ParallaxOnPageChangeListener(viewPager, viewPager2, masterRef));
viewPager2.addOnPageChangeListener(new ParallaxOnPageChangeListener(viewPager2, viewPager, masterRef));
Run Code Online (Sandbox Code Playgroud)
对于自动切换,原始代码工作正常.
由于它很难测试,我想让你们更容易尝试一下,这里是一个Github回购:
[ https://github.com/AndroidDeveloperLB/ParallaxViewPagers ] [4]
请注意,正如我所提到的,它仍然存在问题.主要是"闪烁"效果,但由于某种原因,只有在第二个ViewPager上滚动时才会出现.
| 归档时间: |
|
| 查看次数: |
968 次 |
| 最近记录: |