ViewPager实现左右循环滑动

需求:

  1. RelativeLayout布局中,顶部放置一个RecyclerView作为category,中间放置ViewPager来显示每个category下的内容,而每一个page页的内容使用RecyclerView显示。
  2. 可以循环滑动显示内容。

效果图:

效果图

实现:

对于需求1,是常规操作,在此就不再赘述。接下来看需求2(ViewPager实现左右循环滑动):

平常我们使用ViewPager,无论是page页放置Fragment还是View,都需要一个Adapter。于是我extends的PagerAdapter如下:

public class MyPagerAdapter extends PagerAdapter {
    private List<View> views;

    public MyPagerAdapter(List<View> views) {
        this.views = views;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        container.addView(views.get(position));
        return views.get(position);
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View)object);
    }

    @Override
    public int getCount() {
        return views.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return (view == object);
    }
}

实际上要实现循环滑动,一般可采用两种方式:

其一,新增两个page页,第一个page页作为首页映射“内容页最后page页”,第二个page页作为末尾页,映射“内容页第一page页”,这种实现方式网上可以搜到。但是,这种方式和我的需求1有冲突,category是对应的page页,那么category也要增加两个内容,逻辑上是可以做到,但category映射了position而且使用position访问网络等,简直是牵一发而动全身啊,暂时换个方法试试。。。

其二,看来简单粗暴,但可以解决问题。修改两处:自定义PagerAdapter和ViewPager.OnPageChangeListener的onPageSelected回调。如下:

public class MyPagerAdapter extends PagerAdapter {
    private List<View> views;

    public MyPagerAdapter(List<View> views) {
        this.views = views;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
//        container.addView(views.get(position));
//        return views.get(position);

        //对ViewPager页号求模取出View列表中要显示的项
        position %= views.size();
        if (position<0){
            position = views.size()+position;
        }
        View view = views.get(position);
        //如果View已经在之前添加到了一个父组件,则必须先remove,否则会抛出IllegalStateException。
        ViewParent vp =view.getParent();
        if (vp!=null){
            ViewGroup parent = (ViewGroup)vp;
            parent.removeView(view);
        }
        container.addView(view);
        //add listeners here if necessary
        return view;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
//        container.removeView((View)object);
        //Warning:不要在这里调用removeView
    }

    @Override
    public int getCount() {
//        return views.size();
//        //设置成最大,使用户看不到边界。由于有category对应,值设置为整型最大会导致ANR!!!
//        return Integer.MAX_VALUE;
        return views.size() * 100;
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return (view == object);
    }
}
private ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
        position = position % pageNumber; // 循环滑动
        // ...
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }
};

后记:

看到了一篇文章介绍设置滑动动画(https://www.jianshu.com/p/f70073f7e837  Ps:作者挺厉害的,Android大佬),自己就放到程序中试了下是可以的,代码如下:

mViewPager.setPageTransformer(true, new DepthPageTransformer());
public class DepthPageTransformer implements ViewPager.PageTransformer { // Google官方给出的动画类
    private static final float MIN_SCALE = 0.75f;
    public void transformPage(View view, float position) {
        int pageWidth = view.getWidth();
        if (position < -1) { // [-Infinity,-1)
            // This page is way off-screen to the left.
            view.setAlpha(0);
        } else if (position <= 0) { // [-1,0]
            // Use the default slide transition when moving to the left page
            view.setAlpha(1);
            view.setTranslationX(0);
            view.setScaleX(1);
            view.setScaleY(1);
        } else if (position <= 1) { // (0,1]
            // Fade the page out.
            view.setAlpha(1 - position);
            // Counteract the default slide transition
            // view.setTranslationX(pageWidth * -position);
            view.setTranslationX(pageWidth * -position + 44); // +44是因为ViewPager设置了android:paddingStart="22dp"

            // Scale the page down (between MIN_SCALE and 1)
            float scaleFactor = MIN_SCALE
                    + (1 - MIN_SCALE) * (1 - Math.abs(position));
            view.setScaleX(scaleFactor);
            view.setScaleY(scaleFactor);
        } else { // (1,+Infinity]
            // This page is way off-screen to the right.
            view.setAlpha(0);
        }
    }
}

但是会出现一个问题,点击category切换page到最后一页,再滑动page准备循环,page内容页第一页的透明度就设置成了0。所以现在就没使用这个滑动动画,如果你程序中没有category只有ViewPager,那应该不会出现这个问题。。。

好啦,明天就是六一儿童节咯,祝愿所有童鞋们都能天真如孩童,少掉头发^&^

发布了55 篇原创文章 · 获赞 61 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Agg_bin/article/details/90717452