//创建VirtualLayoutManager对象
VirtualLayoutManager layoutManager = new VirtualLayoutManager(activity);
recyclerView.setLayoutManager(layoutManager);
//设置回收复用池大小,(如果一屏内相同类型的 View 个数比较多,需要设置一个合适的大小,防止来回滚动时重新创建 View)
RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
recyclerView.setRecycledViewPool(viewPool);
viewPool.setMaxRecycledViews(0, 20);
具体做法:
//设置适配器
DelegateAdapter delegateAdapter = new DelegateAdapter(layoutManager, true);
recyclerView.setAdapter(delegateAdapter
/**
* ================================================
* 作 者:杨充
* 版 本:1.0
* 创建日期:2017/9/18
* 描 述:Vlayout框架基类适配器
* 修订历史:
* ================================================
*/
public class BaseDelegateAdapter extends DelegateAdapter.Adapter<BaseViewHolder> {
private LayoutHelper mLayoutHelper;
private int mCount = -1;
private int mLayoutId = -1;
private Context mContext;
private int mViewTypeItem = -1;
protected BaseDelegateAdapter(Context context, LayoutHelper layoutHelper, int layoutId, int count, int viewTypeItem) {
this.mContext = context;
this.mCount = count;
this.mLayoutHelper = layoutHelper;
this.mLayoutId = layoutId;
this.mViewTypeItem = viewTypeItem;
}
@Override
public LayoutHelper onCreateLayoutHelper() {
return mLayoutHelper;
}
@Override
public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == mViewTypeItem) {
return new BaseViewHolder(LayoutInflater.from(mContext).inflate(mLayoutId, parent, false));
}
return null;
}
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
}
/**
* 必须重写不然会出现滑动不流畅的情况
*/
@Override
public int getItemViewType(int position) {
return mViewTypeItem;
}
//条目数量
@Override
public int getItemCount() {
return mCount;
}
}
BaseDelegateAdapter titleAdapter = new BaseDelegateAdapter(activity, new LinearLayoutHelper(),
R.layout.view_vlayout_title, 1, Constant.viewType.typeTitle) {
@Override
public void onBindViewHolder(BaseViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
holder.setText(R.id.tv_title, title);
}
};
private void initRecyclerView() {
DelegateAdapter delegateAdapter = presenter.initRecyclerView(recyclerView);
//把轮播器添加到集合
BaseDelegateAdapter bannerAdapter = presenter.initBannerAdapter();
mAdapters.add(bannerAdapter);
//初始化九宫格
BaseDelegateAdapter menuAdapter = presenter.initGvMenu();
mAdapters.add(menuAdapter);
//初始化
BaseDelegateAdapter marqueeAdapter = presenter.initMarqueeView();
mAdapters.add(marqueeAdapter);
//初始化标题
BaseDelegateAdapter titleAdapter = presenter.initTitle("猜你喜欢");
mAdapters.add(titleAdapter);
//初始化list1
BaseDelegateAdapter girdAdapter = presenter.initList1();
mAdapters.add(girdAdapter);
//初始化标题
titleAdapter = presenter.initTitle("热门新闻");
mAdapters.add(titleAdapter);
//初始化list2
BaseDelegateAdapter linearAdapter = presenter.initList2();
mAdapters.add(linearAdapter);
//初始化标题
titleAdapter = presenter.initTitle("新闻导航");
mAdapters.add(titleAdapter);
//初始化list3
BaseDelegateAdapter girdAdapter3 = presenter.initList3();
mAdapters.add(girdAdapter3);
//初始化标题
titleAdapter = presenter.initTitle("为您精选");
mAdapters.add(titleAdapter);
//初始化list3
BaseDelegateAdapter plusAdapter = presenter.initList4();
mAdapters.add(plusAdapter);
//初始化折叠式指示器控件
//initSticky();
//mAdapters.add(stickyAdapter);
//初始化list控件
titleAdapter = presenter.initTitle("优质新闻");
mAdapters.add(titleAdapter);
linearAdapter = presenter.initList5();
mAdapters.add(linearAdapter);
//设置适配器
delegateAdapter.setAdapters(mAdapters);
}
* 定义:数据适配器。继承自系统的Adaper
* 作用:创建组件 & 绑定数据到组件
* 额外:定义了两个接口:
* getLayoutHelper():用于返回某个位置组件对应的一个 LayoutHelper
* setLayoutHelpers():调用此方法设置整个页面所需要的一系列 LayoutHelper
* 这两方法的具体实现委托给 VirtualLayoutManager 完成
* 定义:布局管理器。继承自系统的 LinearLayoutManager
* 作用:
* 在 RecyclerView 加载组件或者滑动时调用 VirtualLayoutManager 的 layoutChunk(),返回当前还有哪些空白区域可摆放组件
* 管理 LayoutHelper 列表
* 额外:实现了 VirtualLayoutAdapter 的 getLayoutHelper() & setLayoutHelpers()
* 定义:LayoutHelper 寻找器
* 作用:根据页面状态 寻找对应的 LayoutHelper 并返回给 VirtualLayoutManager
* VirtualLayoutManager 会持有一个 LayoutHelperFinder
* 当 layoutChunck() 被调用时会传入一个位置参数,告诉 VirtualLayoutManager 当前要布局第几个组件
* VirtualLayoutManager 通知持有的 LayoutHelperFinder 找到传入参数位置对应的 LayoutHelper(每个 LayoutHelper 都会绑定它负责的布局区域的起始位置和结束位置)
* 定义:布局协助器
* 作用:负责具体的布局逻辑
* 定义:继承自 LayoutHelper
* 作用:扩展 LayoutHelper,提供了布局常用的 内边距padding、外边距margin 的计算功能
* 定义:MarginLayoutHelper 的第一层具体实现
* 作用:填充 当前LayoutHelper 在屏幕范围内的具体区域 背景色、背景图等逻辑
* 定义:MarginLayoutHelper 的第二层具体实现
* 作用:负责具体的布局逻辑
* 每种 子LayoutHelper 负责一种布局逻辑
* 重点实现了 beforeLayout()、doLayout()、afterLayout()
* 特别是 doLayout():会获取一组件,并对组件进行尺寸计算、界面布局
* V - Layout 默认实现了10种默认布局:(对应同名的LayoutHelper)
* 特别注意:
* 每一种 LayoutHelper 负责布局一批组件范围内的组件,不同组件范围内的组件之间,如果类型相同,可以在滑动过程中回收复用。因此回收粒度比较细,且可以跨布局类型复用.
* 支持扩展外部:即注册新的 LayoutHelper,实现特殊的布局方式。下面会详细说明
* 5.1.1 margin, padding
* Margin, padding就是外边距、内边距
* 它不是整个RecyclerView页面的margin和padding,它是每一块LayoutHelper所负责的区域的margin和padding。
* 一个页面里可以有多个LayoutHelper,意味着不同LayoutHelper可以设置不同的margin和padding。
* LayoutHelper的margin和padding与页面RecyclerView的margin和padding可以共存。
* 目前主要针对非fix类型的LayoutHelper实现了margin和padding,fix类型LayoutHelper内部没有相对位置关系,不处理边距。
* 5.1.2 dividerHeight
* LinearLayoutHelper的属性,LinearLayoutHelper是像ListView一样的线性布局,dividerHeight就是每个组件之间的间距。
* 5.1.3 aspectRatio
* 为了保证布局过程中视图的高度一致,我们设计了aspectRatio属性,它是宽与高的比例,LayoutHelper里有aspectRatio属性,通过vlayout添加的视图的LayoutParams也有aspectRatio属性,后者的优先级比前者高,但含义不一样。
* LayoutHelper定义的aspectRatio,指的是一行视图整体的宽度与高度之比,当然整体的宽度是减去了RecyclerView和对应的LayoutHelper的margin, padding。
* 视图的LayoutParams定义的aspectRatio,指的是在LayoutHelper计算出视图宽度之后,用来确定视图高度时使用的,它会覆盖通过LayoutHelper的aspectRatio计算出来的视图高度,因此具备更高优先级。
* 5.1.4 bgColor, bgImg
* 背景颜色或者背景图,这其实不是布局属性,但是由于在vlayout对视图进行了直接布局,不同区域的视图的父节点都是RecyclerView,如果想要针对某一块区域单独绘制背景,就很难做到了。vlayout框架对此做了特殊处理,对于非fix、非float类型的LayoutHelper,支持配置背景色或背景图。同样目前主要针对非fix类型的LayoutHelper实现这个特性。
* 5.1.5 weights
* ColumnLayoutHelper, GridLayoutHelper的属性,它们都是提供网格状的布局能力,建议使用GridLayoutHelper,它的能力更加强大,参考下文介绍。默认情况下,每个网格中每一列的宽度是一样的,通过weights属性,可以指定让每一列的宽度成比例分配,就像LinearLayout的weight属性一样。 weights属性是一个float数组,每一项代表某一列占父容器宽度的百分比,总和建议是100,否则布局会超出容器宽度;如果布局中有4列,那么weights的长度也应该是4;长度大于4,多出的部分不参与宽度计算;如果小于4,不足的部分默认平分剩余的空间。
* 比如,setweights(0.6 , 0.2 , 0.2);那么分配比例是3:1:1
* 5.1.6 vGap, hGap
* GridLayoutHelper与StaggeredGridLayoutHelper都有这两个属性,分别控制视图之间的垂直间距和水平间距。
* 5.1.7 spanCount, spanSizeLookup
* GridLayoutHelper的属性,参考于系统的GridLayoutManager,spanCount表示网格的列数,默认情况下每一个视图都占用一个网格区域,但通过提供自定义的spanSizeLookUp,可以指定某个位置的视图占用多个网格区域
* 5.1.8 autoExpand
* GridLayoutHelper的属性,当一行里视图的个数少于spanCount值的时候,如果autoExpand为true,视图的总宽度会填满可用区域;否则会在屏幕上留空白区域。
* 5.1.9 lane
* StaggeredGridLayoutHelper中有这个属性,与GridLayoutHelper里的spanCount类似,控制瀑布流的列数。
* 5.2.1 fixAreaAdjuster
* fix类型的LayoutHelper,在可能需要设置一个相对父容器四个边的偏移量,比如整个页面里有一个固定的标题栏添加在vlayout容器上,vlayout内部的fix类型视图不希望与外部的标题有所重叠,那么就可以设置一个fixAreaAdjuster来做偏移。
* 5.2.2 alignType, x, y
* FixLayoutHelper, ScrollFixLayoutHelper, FloatLayoutHelper的属性,表示吸边时的基准位置,有四个取值,分别是TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT。x和y是相对这四个位置的偏移量,最终的偏移量还要受上述的fixAreaAdjuster影响。
* TOP_LEFT:基准位置是左上角,x是视图左边相对父容器的左边距偏移量,y是视图顶边相对父容器的上边距偏移量;
* TOP_RIGHT:基准位置是右上角,x是视图右边相对父容器的右边距偏移量,y是视图顶边相对父容器的上边距偏移量;
* BOTTOM_LEFT:基准位置是左下角,x是视图左边相对父容器的左边距偏移量,y是视图底边相对父容器的下边距偏移量;
* BOTTOM_RIGHT:基准位置是右下角,x是视图右边相对父容器的右边距偏移量,y是视图底边相对父容器的下边距偏移量;
* 5.2.3 showType
* ScrollFixLayoutHelper的属性,取值有SHOW_ALWAYS, SHOW_ON_ENTER, SHOW_ON_LEAVE。
* SHOW_ALWAYS:与FixLayoutHelper的行为一致,固定在某个位置;
* SHOW_ON_ENTER:默认不显示视图,当页面滚动到这个视图的位置的时候,才显示;
* SHOW_ON_LEAVE:默认不显示视图,当页面滚出这个视图的位置的时候显示;
* 5.2.4 stickyStart, offset
* StickyLayoutHelper的属性,当视图的位置在屏幕范围内时,视图会随页面滚动而滚动;当视图的位置滑出屏幕时,StickyLayoutHelper会将视图固定在顶部(stickyStart = true)或者底部(stickyStart = false),固定的位置支持设置偏移量offset。