ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示(优化篇)

来源:互联网 发布:阿里云学生服务器搭建 编辑:程序博客网 时间:2024/05/01 09:17

上一张效果图:

之前的项目有一个Galley的项目,但是代码结构特别乱,别问我为什么,我也是刚接手这个项目,为了方便以后阅读和维护我对一些模块进行了重构。ViewPager实现Galler效果,但是当时时间比较急,写的比较仓促,上一篇实现了简单的效果,但是对于初始的时候左边滑动是有问题的,这是因为我们在自己的Adapter的时候对于getCount,我们想通过Integer.MAX_VALUE来实现无限循环,简单的说这个是向右(无限大)吧,所以也就只是实现了向右的循环,对于像左的还是不行的。

那么怎么解决呢?

首先我们对Adapter还是需要按以前的写法,其实Adapter适配器就是帮我们做界面的,其他的逻辑最好不要加,我之前的想法是用过

viewPager.addOnPageChangeListener来实现,通过判断是否滑到最左边或者最右边来实现循环滑到。
 int realPosition = mAdapter.toRealPosition(position);            if (mPreviousPosition != realPosition) {                mPreviousPosition = realPosition;                if (mOuterPageChangeListener != null) {                    mOuterPageChangeListener.onPageSelected(realPosition);                }            }

这里我封装了一个类,只要将你的ViewPager改为我封装好的ViewPager就行
LoopViewPager 
public class LoopViewPager extends ViewPager {    private static final boolean DEFAULT_BOUNDARY_CASHING = false;    private OnPageChangeListener mOuterPageChangeListener;    private LoopPagerAdapterWrapper mAdapter;    private boolean mBoundaryCaching = DEFAULT_BOUNDARY_CASHING;    public static int toRealPosition( int position, int count ){        position = position-1;        if( position < 0 ){            position += count;        }else{            position = position%count;        }        return position;    }        public void setBoundaryCaching(boolean flag) {        mBoundaryCaching = flag;        if (mAdapter != null) {            mAdapter.setBoundaryCaching(flag);        }    }    @Override    public void setAdapter(PagerAdapter adapter) {        mAdapter = new LoopPagerAdapterWrapper(adapter);        mAdapter.setBoundaryCaching(mBoundaryCaching);        super.setAdapter(mAdapter);        setCurrentItem(0, false);    }    @Override    public PagerAdapter getAdapter() {        return mAdapter != null ? mAdapter.getRealAdapter() : mAdapter;    }    @Override    public int getCurrentItem() {        return mAdapter != null ? mAdapter.toRealPosition(super.getCurrentItem()) : 0;    }    public void setCurrentItem(int item, boolean smoothScroll) {        int realItem = mAdapter.toInnerPosition(item);        super.setCurrentItem(realItem, smoothScroll);    }    @Override    public void setCurrentItem(int item) {        if (getCurrentItem() != item) {            setCurrentItem(item, true);        }    }    @Override    public void setOnPageChangeListener(OnPageChangeListener listener) {        mOuterPageChangeListener = listener;    };    public LoopViewPager(Context context) {        super(context);        init();    }    public LoopViewPager(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    private void init() {        super.setOnPageChangeListener(onPageChangeListener);    }    private OnPageChangeListener onPageChangeListener = new OnPageChangeListener() {        private float mPreviousOffset = -1;        private float mPreviousPosition = -1;        @Override        public void onPageSelected(int position) {            int realPosition = mAdapter.toRealPosition(position);            if (mPreviousPosition != realPosition) {                mPreviousPosition = realPosition;                if (mOuterPageChangeListener != null) {                    mOuterPageChangeListener.onPageSelected(realPosition);                }            }        }        @Override        public void onPageScrolled(int position, float positionOffset,                int positionOffsetPixels) {            int realPosition = position;            if (mAdapter != null) {                realPosition = mAdapter.toRealPosition(position);                if (positionOffset == 0                        && mPreviousOffset == 0                        && (position == 0 || position == mAdapter.getCount() - 1)) {                    setCurrentItem(realPosition, false);                }            }            mPreviousOffset = positionOffset;            if (mOuterPageChangeListener != null) {                if (realPosition != mAdapter.getRealCount() - 1) {                    mOuterPageChangeListener.onPageScrolled(realPosition,                            positionOffset, positionOffsetPixels);                } else {                    if (positionOffset > .5) {                        mOuterPageChangeListener.onPageScrolled(0, 0, 0);                    } else {                        mOuterPageChangeListener.onPageScrolled(realPosition,                                0, 0);                    }                }            }        }        @Override        public void onPageScrollStateChanged(int state) {            if (mAdapter != null) {                int position = LoopViewPager.super.getCurrentItem();                int realPosition = mAdapter.toRealPosition(position);                if (state == ViewPager.SCROLL_STATE_IDLE                        && (position == 0 || position == mAdapter.getCount() - 1)) {                    setCurrentItem(realPosition, false);                }            }            if (mOuterPageChangeListener != null) {                mOuterPageChangeListener.onPageScrollStateChanged(state);            }        }    };}

LoopPagerAdapterWrapper
public class LoopPagerAdapterWrapper extends PagerAdapter {    private PagerAdapter mAdapter;    private SparseArray<ToDestroy> mToDestroy = new SparseArray<ToDestroy>();    private boolean mBoundaryCaching;    void setBoundaryCaching(boolean flag) {        mBoundaryCaching = flag;    }    LoopPagerAdapterWrapper(PagerAdapter adapter) {        this.mAdapter = adapter;    }    @Override    public void notifyDataSetChanged() {        mToDestroy = new SparseArray<ToDestroy>();        super.notifyDataSetChanged();    }    int toRealPosition(int position) {        int realCount = getRealCount();        if (realCount == 0)            return 0;        int realPosition = (position-1) % realCount;        if (realPosition < 0)            realPosition += realCount;        return realPosition;    }    public int toInnerPosition(int realPosition) {        int position = (realPosition + 1);        return position;    }    private int getRealFirstPosition() {        return 1;    }    private int getRealLastPosition() {        return getRealFirstPosition() + getRealCount() - 1;    }    @Override    public int getCount() {        return mAdapter.getCount() + 2;    }    public int getRealCount() {        return mAdapter.getCount();    }    public PagerAdapter getRealAdapter() {        return mAdapter;    }    @Override    public Object instantiateItem(ViewGroup container, int position) {        int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter)                ? position                : toRealPosition(position);        if (mBoundaryCaching) {            ToDestroy toDestroy = mToDestroy.get(position);            if (toDestroy != null) {                mToDestroy.remove(position);                return toDestroy.object;            }        }        return mAdapter.instantiateItem(container, realPosition);    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        int realFirst = getRealFirstPosition();        int realLast = getRealLastPosition();        int realPosition = (mAdapter instanceof FragmentPagerAdapter || mAdapter instanceof FragmentStatePagerAdapter)                ? position                : toRealPosition(position);        if (mBoundaryCaching && (position == realFirst || position == realLast)) {            mToDestroy.put(position, new ToDestroy(container, realPosition,                    object));        } else {            mAdapter.destroyItem(container, realPosition, object);        }    }    @Override    public void finishUpdate(ViewGroup container) {        mAdapter.finishUpdate(container);    }    @Override    public boolean isViewFromObject(View view, Object object) {        return mAdapter.isViewFromObject(view, object);    }    @Override    public void restoreState(Parcelable bundle, ClassLoader classLoader) {        mAdapter.restoreState(bundle, classLoader);    }    @Override    public Parcelable saveState() {        return mAdapter.saveState();    }    @Override    public void startUpdate(ViewGroup container) {        mAdapter.startUpdate(container);    }    @Override    public void setPrimaryItem(ViewGroup container, int position, Object object) {        mAdapter.setPrimaryItem(container, position, object);    }    static class ToDestroy {        ViewGroup container;        int position;        Object object;        public ToDestroy(ViewGroup container, int position, Object object) {            this.container = container;            this.position = position;            this.object = object;        }    }}

这里需要注意对于上一篇的WelfareAdapter ,我们就按常规写法就行。
public class WelfareAdapter extends PagerAdapter {    private Context mContext;    private List<PanicBean> dataList = new ArrayList<>();    public WelfareAdapter(Context mContext) {        this.mContext = mContext;    }    public void setDatas(List<PanicBean> list) {        if (list.size() <= 0) {            dataList.clear();            notifyDataSetChanged();            return;        }        dataList.clear();        dataList.addAll(list);        notifyDataSetChanged();    }    @Override    public int getCount() {        return /*Integer.MAX_VALUE*/dataList.size();    }    @Override    public int getItemPosition(Object object) {        return POSITION_NONE;    }    @Override    public void destroyItem(View container, int position, Object object) {    }    @Override    public Object instantiateItem(ViewGroup container, int position) {//        position %= dataList.size();//        if (position<0){//            position = dataList.size()+position;//        }            PanicBean data = dataList.get(position);            ViewHolder viewHolder = null;            View view = LayoutInflater.from(mContext).inflate(                    R.layout.item_finefare_layout, null);            if (viewHolder == null) {                viewHolder = new ViewHolder(view);            }            bindView(viewHolder, data);            container.addView(view, LayoutParams.MATCH_PARENT,                    LayoutParams.MATCH_PARENT);            return view;    }    private void bindView(ViewHolder viewholder, final PanicBean data) {        Glide.with(mContext).load(data.pic).into(viewholder.welfareImage);        viewholder.welfareImage.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                ToastUtils.showToast("你点击了"+data.href);            }        });    }    @Override    public boolean isViewFromObject(View view, Object object) {        return view == object;    }    @Override    public void destroyItem(ViewGroup container, int position, Object object) {        container.removeView((View) object);    }    class ViewHolder {        @BindView(R.id.welfare_image)        RoundedImageView welfareImage;        ViewHolder(View view) {            ButterKnife.bind(this, view);            view.setTag(this);        }        public void reset() {            welfareImage.setBackground(mContext.getResources().getDrawable(R.drawable.welfare_default_icon));        }    }}

部分源码:https://github.com/xiangzhihong/jingdongApp


0 1
原创粉丝点击