现在基本每个资讯类应用都会使用到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<Article> data;
private Context context;
ArticleListBannerAdapter(Context context) {
data = new ArrayList<>();
this.context = context;
}
void addAll(List<Article> 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同步刷新设置的监听。