Recently taobao out of the vlayout, taobao at the beginning of the document is still a little confused, later I also summarized the planning, wrote a more beautiful demo, by the way here to summarize.

VLayout is what, in plain English is to use a native RecycelerView plus VLayout to achieve a more complex layout on a page and have a better reuse, in RecyclerView at the same time GridLayout, waterfall flow layout, Floating layout and other VLayout provides nine layouts, which is also taobao client home page loading different layouts.

Ok, here is a brief introduction, first let’s import VLayout:

compile ('com. Alibaba. Android: vlayout: version@aar') {
    transitive = true
}Copy the code

For the specific version, see the version number given by VLayout in Github. Now the latest version is 1.0.6 and we can start to reference VLayout. The general code for VLayout is as follows:

VirtualLayoutManager manager = new VirtualLayoutManager(this);
recyclerview.setLayoutManager(manager);
DelegateAdapter adapter =new DelegateAdapter(manager, true);Copy the code
  • VirtualLayoutManager which inherits from The LinearLayoutManager; Introduced the concept of LayoutHelper, which is responsible for the specific layout logic; VirtualLayoutManager manages a set of layouthelpers, leaving the specific layout capabilities to LayoutHelper.
  • The DelegateAdapter is a custom Adapter that VLayout makes for LayoutHelper, We put the Adapter that holds the LayoutHelper of various layouts into the DelegateAdapter and then finally recyclerView.setAdapter (DelegateAdapter); You can load a complex layout.
  • VLayout provides nine default layouts that decouple all views and layouts: Linear, Grid, float, fixed position, etc.
  • LinearLayoutHelper: linear layout
  • Grid layout: Grid layout that supports horizontal colspan
  • StaggeredGridLayoutHelper: waterfall flow layout, configurable interval height/width
  • FixLayoutHelper: Fixed layout, always in a fixed position on the screen
  • ScrollFixLayoutHelper: Fixed the layout, but only later when the page slides to the image area is displayed, can be used to return to the top or other bookmarks etc
  • FloatLayoutHelper: Floating layout that can be fixed on the screen, but the user can drag and drop its position
  • ColumnLayoutHelper: layout of columns in one row. You can configure the width ratio of different columns
  • SingleLayoutHelper: A full-column layout that shows only one component View
  • OnePlusNLayoutHelper: a one-drag N layout that can be configured with 1-5 child elements
  • StickyLayoutHelper: Stikcy layout, you can configure top or bottom

These are the classes that correspond to the nine layouts. We can use nine classes to achieve a variety of complex layouts. I will introduce each layout and its effects one by one in order to get a more intuitive view of the effect:

  • LinearLayoutHelper: LinearLayoutHelper: LinearLayoutHelper: LinearLayoutHelper
public class LinearLayoutHelperActivity extends Activity{
    public static RecyclerView recyclerview;
    public static DelegateRecyclerAdapter delegateRecyclerAdapter;
    public DelegateAdapter adapter;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_main);
        recyclerview=(RecyclerView)findViewById(R.id.recyclerview);
        VirtualLayoutManager manager = new VirtualLayoutManager(this);
        recyclerview.setLayoutManager(manager);
        adapter =new DelegateAdapter(manager, true);

        adapter.addAdapter(init(this));
        recyclerview.setAdapter(adapter);
    }

    public static DelegateRecyclerAdapter init(Context context){
        LinearLayoutHelper linearLayoutHelper=new LinearLayoutHelper();
        // Set the interval height
        linearLayoutHelper.setDividerHeight(5);
        // Set the spacing between the bottom of the layout and the next layout
        linearLayoutHelper.setMarginBottom(20);
        // Set the spacing
        linearLayoutHelper.setMargin(20.20.20.20);
        delegateRecyclerAdapter=new DelegateRecyclerAdapter(context,linearLayoutHelper,"LinearLayoutHelper");
        returndelegateRecyclerAdapter; }}Copy the code

The code for DelegateRecyclerAdapter is as follows:

public class DelegateRecyclerAdapter extends DelegateAdapter.Adapter{
    public Context context;
    private LayoutHelper helper;
    private LayoutInflater inflater;
    private String name;

    public DelegateRecyclerAdapter(Context context,LayoutHelper helper,String name){
        this.inflater = LayoutInflater.from(context);
        this.helper = helper;
        this.context=context;
        this.name=name;
    }

    @Override
    public LayoutHelper onCreateLayoutHelper(a) {
        return this.helper;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new MyViewHolder(inflater.inflate(R.layout.layout_item,parent,false));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            if(position%2= =0){
                holder.itemView.setBackgroundColor(0xaa3F51B5);
            }else{
                holder.itemView.setBackgroundColor(0xccFF4081);
            }
        MyViewHolder myViewHolder=(MyViewHolder)holder;
        myViewHolder.name.setText(name+position+"");
    }

    @Override
    public int getItemCount(a) {
        return 9;
    }

    public class MyViewHolder extends RecyclerView.ViewHolder{
        public TextView name;
        public MyViewHolder(View itemView) {
            super(itemView); name=(TextView)itemView.findViewById(R.id.item_name); }}}Copy the code

Adapter class, and then call onCreateLayoutHelper() to return the LayoutHelper class that we passed in, Other and ordinary RecyclerView is the same. The DelegateRecyclerAdapter also has multiple references after us. The other thing to say is that after we initialize the LinearLayoutHelper we produce The DelegateAdapter. The Adapter class assigns to the DelegateAdapter, and then RecyclerView in setAdapter() and that’s it.





image.png

  • GridLayoutHelper: Grid layout, support horizontal colspan, also very simple, the code is as follows:
public static DelegateRecyclerAdapter init(Context context){
        GridLayoutHelper gridLayoutHelper=new GridLayoutHelper(4);
        // Set the number of items in certain positions
        gridLayoutHelper.setSpanSizeLookup(new GridLayoutHelper.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                if (position >5) {
                    return 2;
                }else {
                    return 1; }}});// Whether to fill the available area
        gridLayoutHelper.setAutoExpand(false);
        delegateRecyclerAdapter=new DelegateRecyclerAdapter(context,gridLayoutHelper,"GridLayoutHelper");
        return delegateRecyclerAdapter;
    }Copy the code

The rest of the code is very much the same.





img2.PNG

  • StaggeredGridLayoutHelper: waterfall flow layout, configurable interval height/width, the code is as follows:
 public static StaggeredAdapter init(Context context){
    StaggeredGridLayoutHelper staggeredGridLayoutHelper=new StaggeredGridLayoutHelper(3.20);
    staggeredAdapter=new StaggeredAdapter(context,staggeredGridLayoutHelper,"StaggeredGridLayoutHelper");
    return staggeredAdapter;
 }Copy the code

In StaggeredAdapter we use it in onBindViewHolder

ViewGroup.LayoutParams layoutParams = ((MyViewholder) holder).text.getLayoutParams();
layoutParams.height = 260 + position % 7 * 20;
((MyViewholder) holder).text.setLayoutParams(layoutParams);Copy the code

To achieve height inconsistency, the effect is as follows:





img3.PNG

  • FixLayoutHelper: fixed layout, always in a fixed position on the screen, code as follows:
public static FixLayoutAdapter initFixLayoutHelper(Context context){
    FixLayoutHelper fixLayoutHelper=new FixLayoutHelper(FixLayoutHelper.BOTTOM_LEFT, 200.200);
    FixLayoutAdapter fixLayoutAdapter=new FixLayoutAdapter(context,fixLayoutHelper,"fixlayouthelp");
    return fixLayoutAdapter;
}Copy the code

So in addition to having fixlayouthelper. BOTTOM_LEFT, we have fixlayouthelper. TOP_LEFT, fixlayouthelper. BOTTOM_RIGHT, Fixlayouthelper. TOP_RIGHT, 200,200 correspond to offsets x,y, respectively.





img4.PNG

The FixLayouthelp area block is the FixLayoutHelper.

  • ScrollFixLayoutHelper: Fixed layout, but later when the page slides to the image area is displayed, can be used to return to the top or other bookmarks, etc., code as follows:
public static FixLayoutAdapter initScrollFixLayout(Context context){
    ScrollFixLayoutHelper scrollFixLayoutHelper = new ScrollFixLayoutHelper(15.15);
    //show_always: always displays
    //show_on_enter: displays when the page scrolls to the position of the view
    //show_on_leave: displays when the page rolls out of the position of the view
    scrollFixLayoutHelper.setShowType(ScrollFixLayoutHelper.SHOW_ON_ENTER);
    return new FixLayoutAdapter(context, scrollFixLayoutHelper,"scrollfixlayouthelper");
}Copy the code

The code is very simple, look at the effect:





img5.PNG

ScrollFixLayoutHelper inherits from FixLayoutHelper, but showType determines whether the layout Item is displayed or not, and can be used to do things like return to the top,

  1. SHOW_ALWAYS: fixed in a certain position, consistent with the behavior of FixLayoutHelper.
  2. SHOW_ON_ENTER: the view is not displayed by default. The view is displayed only when the page scrolls to the position of this view.
  3. SHOW_ON_LEAVE: the view is not displayed by default, and is displayed when the page rolls out of the view position;

It’s not obvious here, but once you get all the layout together you can see it’s pretty intuitive

  • FloatLayoutHelper: Floating layout that can be fixed on the screen, but the user can drag and drop its position as follows:
public static FixLayoutAdapter initFloatLayoutHelper(Context context){
    FloatLayoutHelper floatLayoutHelper=new FloatLayoutHelper(a); floatLayoutHelper.setDefaultLocation(20.250);
    FixLayoutAdapter fixLayoutAdapter=new FixLayoutAdapter(context,floatLayoutHelper,"floatlayouthelper");
    return  fixLayoutAdapter;
}Copy the code

The effect is as follows:





img6.gif

Where setDefaultLocation() is used to set its initial position, setAlignType (the base position on which the edge is drawn, the default upper left corner, has four values, They’re TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT.

  • ColumnLayoutHelper: column grid layout, all in a row layout, you can configure the width ratio between different columns, the code is as follows:
 public static ColumnLayoutAdapter initColumnLayout(Context context){
    ColumnLayoutHelper columnLayoutHelper=new ColumnLayoutHelper(a); columnLayoutHelper.setWeights(new float[] {20.20.20.20.20});
    columnLayoutHelper.setMarginBottom(20);
    ColumnLayoutAdapter columnLayoutAdapter=new ColumnLayoutAdapter(context,columnLayoutHelper,"ColumnLayoutHelper");
    return columnLayoutAdapter;
}Copy the code

ColumnLayoutHelper requires Weights, which is a float array with a sum of 100, otherwise out of the layout. The renderings are as follows:





img7.PNG

  • SingleLayoutHelper: open column layout, only one component View will be displayed, here it is recommended to set the number of Adapter as 1, because it will only show one column, if there are more than one column may appear some problems, I measured the number of points will be a problem. The code is as follows:
public static SingleLayoutAdapter initSingleLayout(Context context){
    SingleLayoutHelper singleLayoutHelper=new SingleLayoutHelper(a);// Set the spacing
    singleLayoutHelper.setMargin(20.20.20.20);
    SingleLayoutAdapter singleLayoutAdapter=new SingleLayoutAdapter(context,singleLayoutHelper,"SingleLayoutHelper");
    return singleLayoutAdapter;
}Copy the code

The renderings are as follows:





img8.PNG

  • OnePlusNLayoutHelper: a one-drag N layout, can be configured with 1-5 child elements, according to the number of different interface is also different, different numbers of effects as follows:

// The number is 1





Number is 1. PNG

// The number is 2





Number is 2. PNG

// The number is 3





Number for the 3. PNG

// The number is 4





Number 4. PNG

// The number is 5





The number of 5. PNG

The code is as follows:

 public static OnePlusNLayoutAdapter initOnePlusNLayout(Context context){
    OnePlusNLayoutHelper onePlusNLayoutHelper=new OnePlusNLayoutHelper(a);// Set the spacing between the bottom of the layout and the next layout
    onePlusNLayoutHelper.setMarginBottom(20);
    OnePlusNLayoutAdapter onePlusNLayoutAdapter=new OnePlusNLayoutAdapter(context,onePlusNLayoutHelper,"OnePlusNLayoutHelper");
    return onePlusNLayoutAdapter;
}Copy the code
  • StickyLayoutHelper: Stikcy layout, you can configure the top or bottom, the code is as follows:
public static StickyLayoutAdapter initStickyLayoutHelper(Context context){
    StickyLayoutHelper stickyLayoutHelper=new StickyLayoutHelper(a);return new StickyLayoutAdapter(context,stickyLayoutHelper);
}Copy the code

The renderings are as follows:





img10.gif

  • Finally, if only one of the layouts is loaded, the biggest significance of VLayout is to load multiple layouts and maintain a good reuse, so we put all of the above layout together, the code is as follows:
public class AllActivity extends Activity{

    private RecyclerView recyclerview;
    private DelegateAdapter delegateAdapter ;
    final List<DelegateAdapter.Adapter> adapters = new LinkedList<>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_main);
        recyclerview=(RecyclerView)findViewById(R.id.recyclerview);

        initView();
    }

    public void initView(){
        RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();
        recyclerview.setRecycledViewPool(viewPool);
        viewPool.setMaxRecycledViews(0.10);

        adapters.add(LinearLayoutHelperActivity.init(this));
        adapters.add(ColumnLayoutHelperActivity.initColumnLayout(this));
        adapters.add(GridLayoutHelperActivity.init(this));
        adapters.add(FixLayoutHelperActivity.initFixLayoutHelper(this));
        adapters.add(ScrollFixLayoutHelperActivity.initScrollFixLayout(this));
        adapters.add(SingleLayoutHelperActivity.initSingleLayout(this));
        adapters.add(OnePlusNLayoutHelperActivity.initOnePlusNLayout(this));
        adapters.add(FloatLayoutHelperActivity.initFloatLayoutHelper(this));
        adapters.add(StickyLayoutHelperActivity.initStickyLayoutHelper(this));
        adapters.add(StaggeredGridLayoutHelperActivity.init(this));

        VirtualLayoutManager manager = new VirtualLayoutManager(this);
        recyclerview.setLayoutManager(manager);
        delegateAdapter = newDelegateAdapter(manager); delegateAdapter.setAdapters(adapters); recyclerview.setAdapter(delegateAdapter); }}Copy the code

DelegateAdapter = New DelegateAdapter(layoutManager, hasConsistItemType); When hasConsistItemType=true, items of the same type can be reused regardless of whether they belong to the same subadapter. Indicates that they share a type. When hasConsistItemType=false, the types of different child adapters are not shared.

The effect is shown below:





img11.gif

Finally source code demo, the code is in this github.com/jack921/Pro…