A friend who does a business-like application may encounter a headache: how a complex home page layout can be implemented. Refer to Baidu Glutinous rice, American Regiment, Bilibili and other applications, will find its home page layout is relatively complex, such as Bilibili's homepage (the second one is the demo implementation), you can see in the same page first has a list layout appears, then there are 2 columns of grid layout, and then 3 columns of grid layout, Finally there is the waterfall flow layout:
What is the effect of this? Are you using Linearlayoutmanager, Gridlayoutmanager, or Staggeredgridlayoutmanager? Or is not used at all Recycleview, is the use of scrollview hard layout implementation? Or is it possible to use multiple recycleview for nesting to achieve the layout of 3 mixed layouts?
Let's sort through one line:
- First of all, we found that the length of the page is infinite length, you can constantly pull down the refresh, all the possibility of excluding ScrollView, the basic assertion is that the use of Recyclerview
- We notice that the layout of the mixed layouts in 3 appears on the same page, possibly using Recycleview for 2 levels of nesting, nesting grids and waterfalls in the linear Recycleview Recycleview?
- If there is no nesting, is there a way to implement these 3 effects with a custom layout manager?
- Is it possible to use some 3-party controls?
For the above 3 questions, I provide 3 different solutions to achieve the effect:
Scenario One: Level 2 nesting of Recyclerview
When you see 3 mixed layouts in the same scroll control, most of the first images are nested.
If nested, what is nested? From the point of view, the number of views in a column seems to be fixed, which means you can use layouts such as relativelayout for hard typography. It's certainly better if it's really fixed, but notice that when you click on the Refresh button on each column, there are occasional animations of two view swap locations, which are unique to Recyclerview, and no one has told me that the number of views in each column is fixed, and in case there is a row in any one day, So we're still nesting recyclerview, specifically nested rules such as:
In fact, the outermost RecyclerView1 replaced ScrollView can also, as long as the internal recyclerview sequentially splicing up can be, realize it is more simple, the realization of the way thousands, I choose a favorite, I just to facilitate the expansion, In case you need to add dynamic columns.
The previous article on the Recyclerview nested problem, to each recyclerview set corresponding to the Fully****layoutmanager can be. Specific implementation see the source code, I will not post, re-getitemviewtype method for each position location of the item set a different type, and then oncreateviewholder to create the corresponding holder, Finally, onbindviewholder the sub-recyclerview of different fully layouts for different types of item.
On the key code (with limitations):
@Override Public void Onbindviewholder(Recyclerview.viewholder holder,intPosition) {if(HolderinstanceofMyViewHolder1) {Holder.child_recyclerView.setLayoutManager (NewFullylinearlayoutmanager (context)); }Else if(HolderinstanceofMyViewHolder2) {Holder.child_recyclerView.setLayoutManager (NewFullygridlayoutmanager (Context,2, Gridlayoutmanager.vertical,false)); }Else if(HolderinstanceofMyViewHolder3) {Holder.child_recyclerView.setLayoutManager (NewFullygridlayoutmanager (Context,3, Gridlayoutmanager.vertical,false)); }Else if(HolderinstanceofMYVIEWHOLDER4) {Holder.child_recyclerView.setLayoutManager (NewFullygridlayoutmanager (Context,3, Gridlayoutmanager.vertical,false)); } }
This way I do not introduce, because in the previous article also said that Google does not recommend Recyclerview, ListView nesting, nested use then the view reuse mechanism is tantamount to a waste, will still be initialized at the first load of all the item, If the amount of data is too large to create a performance barrier, so I also follow Google's recommendations do not recommend the use of nested solutions, I would recommend the following scenario.
Scenario two: Using a special (custom) layout manager
This scenario is what I think is the best approach, and it fits perfectly with the standards set by Google: Using the layout Manager to manage the layout. We continue to look at the diagram of the homepage layout, do we really want to write a layout manager for this hybrid layout? We found a mix of 3 cross-mixed layouts with lists, grids, and waterfall streams. Let's put the waterfall on the side and think about it. If we set the number of columns in the grid to 1 columns, that's not a list layout, that is, we can use the Grid Layout manager to make the list style, so that is to say with the custom layout manager, but actually do not need our custom, Gridlayoutmanager provides us with a way to dynamically change the number of columns each item occupies:
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override publicintgetSpanSize(int position) { return gridManager.getSpanCount(); }}
Getspansize method, the return value indicates how many columns the current item occupies, for example, if we set the number of columns to 3 columns, returning 3 means full, which is the same as the list.
, we give Recyclerview a gridlayoutmanager with a number of 6 columns, and then dynamically set spansize for different parts of the item to be 6 (paved), 3 (1/2), 2 (1/3) on the line.
Set a gridlayoutmanager with a number of 6 columns:
recyclerView.setLayoutManager(new GridLayoutManager(recyclerView.getContext6, GridLayoutManager.VERTICAL, false));
Dynamically set different spansize for different position in the Onattachedtorecyclerview method:
@Override Public void Onattachedtorecyclerview(FinalRecyclerview Recyclerview) {Super. Onattachedtorecyclerview (Recyclerview); Recyclerview.layoutmanager manager = Recyclerview.getlayoutmanager ();if(ManagerinstanceofGridlayoutmanager) {FinalGridlayoutmanager Gridmanager = ((Gridlayoutmanager) manager); Gridmanager.setspansizelookup (NewGridlayoutmanager.spansizelookup () {@Override Public int getspansize(intPosition) {intType = Getitemviewtype (position);Switch(type) { CaseType_slider: CaseType_type2_head: CaseType_type3_head:return 6; CaseType_type2:return 3; CaseType_type3:return 2;default:return 3; } } }); } }
So a friend is going to ask, well the waterfall flow?
I looked up the staggeredgridlayoutmanager and found that it did not provide a way to dynamically set up the columns, but provided a method in Staggeredgridlayoutmanager.layoutparams:
LayoutParams.setFullSpan(true);
The function is to set the width of the current item to full (fill), that is, if the use of Staggeredgridlayoutmanager is either not set, or can only be filled, so can not complete the effect on the graph, we do not have to completely imitate it, Bilibili also abandoned the use of waterfall streaming layouts after the latest update, unifying the list and grid formats.
Of course, if you want to achieve the effect on the diagram is not no way, only need to change one way, change the item, set to Fullspan item set to a multiple view combination of composite item on the line, put a diagram, the code is not on:
Scenario three: Using third-party controls to implement
I almost went through the three-party recyclerview on GitHub and finally found a very interesting twoway-view
Twowayview is a special Twowayview that inherits from the Recyclerview in its function, which realizes the layout manager which can be dynamically arranged freely, and can realize the list, grid, waterfall, table layout. Powerful, the main use of its waterfall flow to achieve the effect:
Add Dependencies:
repositories { mavenurl"https://oss.sonatype.org/content/repositories/snapshots/" } url"https://jitpack.io" }}dependencies { compile‘org.lucasr.twowayview:core:1.0.0-SNAPSHOT@aar‘ ‘org.lucasr.twowayview:layouts:1.0.0-SNAPSHOT@aar‘}
To add a layout:
<org.lucasr.twowayview.widget.TwoWayView android:id="@+id/twowayView" android:scrollbars="vertical" android:layout_width="match_parent" android:layout_height="match_parent" app:twowayview_layoutManager="StaggeredGridLayoutManager" app:twowayview_numColumns="6" />
Twowayview supports setting the layout manager in properties so that it does not have to be set in the code, set the number of columns to 6 columns
To set the adapter:
public class TwowayRecycleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ... } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { ... } @Override public int getItemCount() { ... } @Override public int getItemViewType(int position) { ... }}
See Demo for specific code, just focus on:
Implement the Getitemviewtype method to divide different item types:
@Override Public int Getitemviewtype(intPosition) {if(Position = =0){returnType_slider; }Else if(Position = =1){returnType_type2_head; }Else if(2<=position && Position <=7){returnType_type2; }Else if(Position = =8){returnType_type3_head; }Else if(9<=position && Position <= -){returnType_type3; }Else if( the<=position && Position <= -){returnType_type4; }Else{returnType_type5; } }
@Override Public void Onbindviewholder(Recyclerview.viewholder holder,intPosition) {View Itemview = Holder.itemview;FinalStaggeredgridlayoutmanager.layoutparams LP = (staggeredgridlayoutmanager.layoutparams) itemView.getLayoutParams ();Switch(Getitemviewtype (position)) { CaseType_slider: CaseType_type2_head: CaseType_type3_head: CaseTYPE_TYPE4:lp.span =6; Break; CaseTYPE_TYPE2:lp.span =3; Break; CaseTYPE_TYPE3:lp.span =2; Break; CaseTYPE_TYPE5:lp.span =3;if(Position%3==0) {Lp.height = $; }Else if(Position%5==0) {Lp.height = -; }Else if(Position%7==0) {Lp.height = -; }Else{lp.height = -; } Break; } itemview.setlayoutparams (LP); ... }
Determine the type of the item by its position in Onbindviewholder, and then set the item's span (and the number of columns), height (altitude, not set to the item itself)
Which is the best option?
Of the 3 scenarios above, there is no doubt that the second is the best solution, without the introduction of too much reliance, fully using the features of the Recyclerview layout manager to achieve the best performance. The third scenario is actually the implementation of a special layout manager to achieve special typography and the second principle is the same, but the second scenario is the use of Google's own tools, and the latter is a re-implementation. But Twowayview can do more support, such as Grid layout (see Github:twoway-view), is also a good way, and the first solution I will not say, not recommended, This nesting not only makes the logic of the code complicated and messy (I almost don't spit when I write nested in the demo), but also has a performance barrier, so give a conclusion: 2>3>1
Download
Finally, attach the demo download:
Demo
Android Development Travel: Recycleview Implementation of complex home layout three ways