ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示(优化篇)详解手机开发

上一张效果图:

ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示(优化篇)详解手机开发
ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示(优化篇)详解手机开发
ViewPager 实现 Galler 效果, 中间大图显示,两边小图展示(优化篇)详解手机开发

之前的项目有一个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

 

原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/5653.html

(0)
上一篇 2021年7月17日
下一篇 2021年7月17日

相关推荐

发表回复

登录后才能评论