Android 封装自定义无限轮播banner之体验装饰模式

现在基本每个资讯类应用都会使用到banner来无限轮播,现在项目中使用别人封装的ViewPager总会遇到不可预知的问题,修改起来也十分麻烦,于是决定自己封装一个,在使用适配器的时候遇到一个问题,就是虽然是ViewPage的PageAdapter逻辑部分肯定是要留给使用者去写的,但是adapter给他写了之后,我还要在里面扩展上无限轮播的功能,例如getCount()里我要给它加上一个2。所以这里就要使用上装饰者模式来扩展一下了。

简单介绍一下装饰模式
(1)抽象组件:定义一个抽象接口,来规范准备附加功能的类

(2)具体组件:将要被附加功能的类,实现抽象构件角色接口

(3)抽象装饰者:持有对具体构件角色的引用并定义与抽象构件角色一致的接口

(4)具体装饰:实现抽象装饰者角色,负责对具体构件添加额外功能。

(引用自https://www.cnblogs.com/chenxing818/p/4705919.html)。
里面有具体的代码示例来讲解装饰模式,通俗易懂。

实际的使用:

首先写一个正常的pageAdapter

class ArticleListBannerAdapter extends PagerAdapter {
    private List
data; private Context context; ArticleListBannerAdapter(Context context) { data = new ArrayList<>(); this.context = context; } void addAll(List
data) { this.data = data; } void clear(){ data.clear(); } @Override public int getCount() { return data.size(); } @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public Object instantiateItem(ViewGroup container, int position) { //业务逻辑。。。。。 ItemHeadHomeBinding itemHeadHomeBinding; container.addView(itemHeadHomeBinding.getRoot()); return itemHeadHomeBinding.getRoot(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View) object); } }

然后就是自定义ViewPager中新建一个包装类:

 private class BannerAdapterWrapper extends PagerAdapter {
        private PagerAdapter pagerAdapter;

        public BannerAdapterWrapper(PagerAdapter pagerAdapter) {
            this.pagerAdapter = pagerAdapter;
        }

        @Override
        public int getCount() {
            return pagerAdapter.getCount() > 1 ? pagerAdapter.getCount() + 2 : pagerAdapter.getCount();
        }

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

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            return pagerAdapter.instantiateItem(container, bannerToAdapterPosition(position));
        }

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

        /**
         * position 转换
         *
         * @param position
         * @return
         */
        public int bannerToAdapterPosition(int position) {
            int adapterCount = adapter.getCount();
            if (adapterCount <= 1) return 0;
            int adapterPosition = (position - 1) % adapterCount;
            if (adapterPosition < 0) adapterPosition += adapterCount;
            return adapterPosition;
        }

        public int toWrapperPosition(int position) {
            return position + 1;
        }
    }

两个Position方法是adapter和adapterWrapper的position不一致之前的相互转换。

然后重写setAdatper方法

    private BannerAdapterWrapper bannerAdapterWrapper;
    private PagerAdapter adapter;
    private BannerAdapterWrapper bannerAdapterWrapper;
    private PagerAdapter adapter;
    @Override
    public void setAdapter(PagerAdapter adapter) {
        this.adapter = adapter;
        this.adapter.registerDataSetObserver(new BannerPagerObserver());
        bannerAdapterWrapper = new BannerAdapterWrapper(adapter);
        super.setAdapter(bannerAdapterWrapper);
        addOnPageChangeListener(new BannerPageChangeListener());
    }

注意:
this.adapter.registerDataSetObserver(new BannerPagerObserver());是为了让原来的adapter数据刷新的时候能让adapterWrapper同步刷新设置的监听。

你可能感兴趣的:(android)