VLayout在处理RecyclerView多布局时使用了分块Adapter,也就是一个RecyclerView存在多个Adapter。最后通过一个总的Adapter整合了所有。
核心类
VirtualLayoutManager
重写了RecyclerView的原生LinearLayoutManager,来间接管理各个Adapter,所以使用VLayout必然要配置VirtualLayoutManager。
VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(this);
VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(this);
recyclerView.setLayoutManager(virtualLayoutManager);
LayoutHelper
如果VirtualLayoutManager是间接管理各个Adapter,那么 LayoutHelper就是负责管理自己所属的Adapter。VLayout的多样化也正是体现在了LayoutHelper子类的多样化。
-
LinearLayoutHelper(线性布局)
-
GridLayoutHelper(网格布局)
-
FixLayoutHelper(固定布局)
-
ScrollFixLayoutHelper(可选的固定布局)
-
FloatLayoutHelper(浮动布局)
-
ColumnLayoutHelper(格栅布局)
-
SingleLayoutHelper(通栏布局)
-
OnePlusNLayoutHelper(一拖N布局)
-
StickyLayoutHelper(吸边布局)
-
StaggeredGridLayoutHelper(瀑布流布局)
VLayout提供了这10种布局效果,基本上已经可以应付我们碰到的各种需求。
创建一种布局Adapter
public class LinearAdapter extends DelegateAdapter.Adapter<LinearAdapter.MyHolder> {
List<String> data;
public LinearAdapter(List<String> data) {
this.data = data;
}
@Override
public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TextView textView = new TextView(parent.getContext());
textView.setBackgroundColor(Color.WHITE);
textView.setLayoutParams(new ViewGroup.LayoutParams(-1, 100));
return new MyHolder(textView);
}
@Override
public void onBindViewHolder(MyHolder holder, int position) {
holder.textView.setText(data.get(position));
}
@Override
public int getItemCount() {
return data.size();
}
@Override
public int getItemViewType(int position) {
return 0;
}
@Override
public LayoutHelper onCreateLayoutHelper() {
LinearLayoutHelper l = new LinearLayoutHelper();
return l;
}
//View被回收时调用
@Override
public void onViewRecycled(@NonNull MyHolder holder) {
super.onViewRecycled(holder);
}
//由于VLayout将整个布局分割开每个Item之间已经没有了关联,所以VLayout提供了这个方法 offsetTotal反应了总的position
@Override
protected void onBindViewHolderWithOffset(MyHolder holder, int position, int offsetTotal) {
super.onBindViewHolderWithOffset(holder, position, offsetTotal);
}
public static class MyHolder extends RecyclerView.ViewHolder {
TextView textView;
public MyHolder(View itemView) {
super(itemView);
textView = (TextView) itemView;
}
}
}
继承于DelegateAdapter.Adapter用法与RecyclerView.Adapter相同,这里多了个硬性重写方法onCreateLayoutHelper() 返回一个layoutHelper,也就是指定当前Adapter需要使用哪种类型。 我们指定一个线性的。
组装各个Adapter
VirtualLayoutManager virtualLayoutManager = new VirtualLayoutManager(this);
recyclerView.setLayoutManager(virtualLayoutManager);
DelegateAdapter delegateAdapter = new DelegateAdapter(virtualLayoutManager, true);
delegateAdapter.addAdapter(new LinearAdapter(getData()));
delegateAdapter.addAdapter(new FixAdapter());
recyclerView.setAdapter(delegateAdapter);
RecyclerView.RecycledViewPool pool = new RecyclerView.RecycledViewPool();
pool.setMaxRecycledViews(0, 20);
recyclerView.setRecycledViewPool(pool);
通过DelegateAdapter将各个DelegateAdapter.Adapter包装起来实现了RecyclerView的多样化。如果一屏内相同类型的 View 个数比较多,需要设置一个合适的大小,防止来回滚动时重新创建 View使用自定义的复用池。
LayoutHelper属性详情
公共属性
layoutHelper.setItemCount(4);// 设置布局里Item个数
layoutHelper.setPadding(10,10,10,10);// 设置LayoutHelper的子元素相对LayoutHelper边缘的距离
layoutHelper.setMargin(10,10,10,10);// 设置LayoutHelper边缘相对父控件(即RecyclerView)的距离
layoutHelper.setBgColor(Color.GRAY);// 设置背景颜色
layoutHelper.setAspectRatio(6);// 设置设置布局内每行布局的宽与高的比
私有属性
linearLayoutHelper.setDividerHeight(1); // 设置每行Item的距离
gridLayoutHelper.setWeights(new float[]{40, 30, 30});//设置每行中 每个网格宽度 占 每行总宽度 的比例
gridLayoutHelper.setVGap(20);// 控制子元素之间的垂直间距
gridLayoutHelper.setHGap(20);// 控制子元素之间的水平间距
gridLayoutHelper.setAutoExpand(false);//是否自动填充空白区域
gridLayoutHelper.setSpanCount(3);// 设置每行多少个网格
// 通过自定义SpanSizeLookup来控制某个Item的占网格个数
gridLayoutHelper.setSpanSizeLookup(new GridLayoutHelper.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (position > 7 ) {
return 3;
// 第7个位置后,每个Item占3个网格
}else {
return 2;
// 第7个位置前,每个Item占2个网格
}
}
});
fixLayoutHelper.setAlignType(FixLayoutHelper.TOP_LEFT);// 设置吸边时的基准位置(alignType)
fixLayoutHelper.setX(30);// 设置基准位置的横向偏移量X
fixLayoutHelper.setY(50);// 设置基准位置的纵向偏移量Y
scrollFixLayoutHelper.setAlignType(FixLayoutHelper.TOP_LEFT);// 设置吸边时的基准位置(alignType)
scrollFixLayoutHelper.setX(30);// 设置基准位置的横向偏移量X
scrollFixLayoutHelper.setY(50);// 设置基准位置的纵向偏移量Y
scrollFixLayoutHelper.setShowType(ScrollFixLayoutHelper.SHOW_ON_ENTER);// 设置Item的显示模式
SHOW_ALWAYS:永远显示(即效果同固定布局)
SHOW_ON_ENTER:默认不显示视图,当页面滚动到该视图位置时才显示;
SHOW_ON_LEAVE:默认不显示视图,当页面滚出该视图位置时才显示
floatLayoutHelper.setDefaultLocation(300,300);// 设置布局里Item的初始位置
columnLayoutHelper.setWeights(new float[]{30, 40, 30});// 设置该行每个Item占该行总宽度的比例
stickyLayoutHelper.setStickyStart(true);
// true = 组件吸在顶部
// false = 组件吸在底部
stickyLayoutHelper.setOffset(100);// 设置吸边位置的偏移量
staggeredGridLayoutHelper.setLane(3);// 设置控制瀑布流每行的Item数
staggeredGridLayoutHelper.setHGap(20);// 设置子元素之间的水平间距
staggeredGridLayoutHelper.setVGap(15);// 设置子元素之间的垂直间距
参照