RecyclerView Grid的LayoutManager具有不同的单元宽度 [英] LayoutManager for RecyclerView Grid with different cell width
问题描述
StaggeredGridLayoutManager
似乎不允许自定义单元格宽度或跨垂直方向的多列(除了全跨度)。 >
什么是首选 LayoutManager
用于组织单元格,如上所示?
PS 我只想知道如何自定义 / strong>,而不是高度 StaggeredGridLayoutManager
。我知道身高可以通过
如何增加单元格0宽度与单元格1相比 StaggeredGridLayoutManager
或其他任何布局管理器
c> StaggeredGridLayoutManager.LayoutParams 来改变单元格的宽度和高度,你期望设计遵循一个简单的模式,如果你为每个单元格分配一个索引(按照 StaggeredGridLayoutManager
默认安排它们)你会得到这个:
index%4 == 3 ---> ;满量程单元
索引%8 == 0,5 --->半跨单元
索引%8 == 1,2,4,6 --->首先在适配器中声明一些常量以定义跨度类型:$ b $
b
private static final int TYPE_FULL = 0;
private static final int TYPE_HALF = 1;
private static final int TYPE_QUARTER = 2;
然后在您的适配器中覆盖 getItemViewType
方法这:
@Override
public int getItemViewType(int position){
final int modeEight = position% 8;
switch(modeEight){
case 0:
case 5:
return TYPE_HALF;
案例1:
案例2:
案例4:
案例6:
返回TYPE_QUARTER;
}
返回TYPE_FULL;
}
您需要做的是更改layoutparams,考虑 viewType
持有人
:
@Override
public MyHolder onCreateViewHolder(final ViewGroup parent,final int viewType){
final查看itemView =
LayoutInflater.from(mContext).inflate(R.layout.items,parent,false);
itemView.getViewTreeObserver()。addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener(){
@Override
public boolean onPreDraw(){
final int type = viewType;
final ViewGroup.LayoutParams lp = itemView.getLayoutParams();
if(lp instanceof StaggeredGridLayoutManager.LayoutParams){
StaggeredGridLayoutManager.LayoutParams sglp =
(StaggeredGridLayoutManager.LayoutParams)lp;
switch(类型){
case TYPE_FULL:
sglp.setFullSpan(true);
break;
case TYPE_HALF:
sglp.setFullSpan(false);
sglp .width = itemView.getWidth()/ 2;
break;
case TYPE_QUARTER:
sglp.setFullSpan(false);
sglp.width = itemView.getWidth()/ 2;
sglp.height = itemView.getHeight()/ 2;
休息;
}
itemView.setLayoutParams(sglp);
final StaggeredGridLayoutManager lm =
(StaggeredGridLayoutManager)((RecyclerView)parent).getLayoutManager();
lm.invalidateSpanAssignments();
}
itemView.getViewTreeObserver()。removeOnPreDrawListener(this);
返回true;
}
});
MyHolder holder = new MyHolder(itemView);
回报持有者;
$ / code>
我的适配器总是返回50个项目计数(只是一个测试),我用一个简单的项目布局文件,它包含一个 LinearLayout
和一个 TextView
来显示持有者的位置。由于您的设计,传递2给 spanCount
(int StaggeredGridLayoutManager
构造函数)。
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView rv =(RecyclerView)findViewById(R.id.rv);
StaggeredGridLayoutManager lm =
StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
rv.setLayoutManager(lm);
rv.setAdapter(new MyAdapter(this));
PS :
对于像我这样的懒惰人来说,这可能是一种更简单的方式,而不是扩展我的自定义 / code>,但我相信有更好的方法来实现这一点。
更新:
更新了部分你可以使用 GridLayoutManager
:
GridLayoutManager glm = new GridLayoutManager(this,3);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup(){
@Override
public int getSpanSize(int position){$ b $ if(位置%3 == 2){
返回3;
}
开关(位置%4){
案例1:
案例3:
返回1;
案例0:
案例2:
返回2;
默认值:
//永远不会发生
返回-1;
}
}
} );
rv.setLayoutManager(glm);
通过这种方式,您可以为默认跨度大小设置3,然后考虑跨度的位置,占据1,2或3个跨度,像这样:
Item0.width == 2 X Item1.width
Item2.width == 3 X Item1.width
Item0.width == 2/3 X Item1 .width
StaggeredGridLayoutManager
doesn't seem to allow customising a cell width or span multiple columns (except full span) for vertical orientation.
What is a preferred LayoutManager
for organising cells as shown above?
P.S. I just want to know how to customise cell width and not height with StaggeredGridLayoutManager
. I know height can be customised as implemented in this sample.
public class VerticalStaggeredGridFragment extends RecyclerFragment {
public static VerticalStaggeredGridFragment newInstance() {
VerticalStaggeredGridFragment fragment = new VerticalStaggeredGridFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
@Override
protected RecyclerView.LayoutManager getLayoutManager() {
return new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
}
@Override
protected RecyclerView.ItemDecoration getItemDecoration() {
return new InsetDecoration(getActivity());
}
@Override
protected int getDefaultItemCount() {
return 100;
}
@Override
protected SimpleAdapter getAdapter() {
return new SimpleStaggeredAdapter();
}
}
Adapter
public class SimpleStaggeredAdapter extends SimpleAdapter {
@Override
public void onBindViewHolder(VerticalItemHolder itemHolder, int position) {
super.onBindViewHolder(itemHolder, position);
final View itemView = itemHolder.itemView;
if (position % 4 == 0) {
int height = itemView.getContext().getResources()
.getDimensionPixelSize(R.dimen.card_staggered_height);
itemView.setMinimumHeight(height);
} else {
itemView.setMinimumHeight(0);
}
}
}
itemView.setMinimumWidth(customWidth)
doesn't affect cell width.
To simplify, I update my grid layout to
How to increase cell 0 width as compared to cell 1 in a StaggeredGridLayoutManager
or any other layout manager?
You can use StaggeredGridLayoutManager.LayoutParams
to change width and height of cells, What you expect to design follows a simple pattern, If you assign every cell an index (in the order that StaggeredGridLayoutManager
arranges them by default) you will have this:
index % 4 == 3 ---> full span cell
index % 8 == 0, 5 ---> half span cell
index % 8 == 1, 2, 4, 6 ---> quarter span cell
first declare some constants in adapter to define span types:
private static final int TYPE_FULL = 0;
private static final int TYPE_HALF = 1;
private static final int TYPE_QUARTER = 2;
Then override getItemViewType
method in your adapter like this:
@Override
public int getItemViewType(int position) {
final int modeEight = position % 8;
switch (modeEight) {
case 0:
case 5:
return TYPE_HALF;
case 1:
case 2:
case 4:
case 6:
return TYPE_QUARTER;
}
return TYPE_FULL;
}
All you need to do is change layoutparams considering viewType
of the holder
:
@Override
public MyHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {
final View itemView =
LayoutInflater.from(mContext).inflate(R.layout.items, parent, false);
itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
final int type = viewType;
final ViewGroup.LayoutParams lp = itemView.getLayoutParams();
if (lp instanceof StaggeredGridLayoutManager.LayoutParams) {
StaggeredGridLayoutManager.LayoutParams sglp =
(StaggeredGridLayoutManager.LayoutParams) lp;
switch (type) {
case TYPE_FULL:
sglp.setFullSpan(true);
break;
case TYPE_HALF:
sglp.setFullSpan(false);
sglp.width = itemView.getWidth() / 2;
break;
case TYPE_QUARTER:
sglp.setFullSpan(false);
sglp.width = itemView.getWidth() / 2;
sglp.height = itemView.getHeight() / 2;
break;
}
itemView.setLayoutParams(sglp);
final StaggeredGridLayoutManager lm =
(StaggeredGridLayoutManager) ((RecyclerView) parent).getLayoutManager();
lm.invalidateSpanAssignments();
}
itemView.getViewTreeObserver().removeOnPreDrawListener(this);
return true;
}
});
MyHolder holder = new MyHolder(itemView);
return holder;
}
My adapter always returns 50 for items count(just a test) and I used a simple layout file for items, It contains a LinearLayout
and a TextView
to show the position of holder, Remember you should pass 2 for spanCount
(int the StaggeredGridLayoutManager
constructor) because of your design.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView rv = (RecyclerView) findViewById(R.id.rv);
StaggeredGridLayoutManager lm =
new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL);
rv.setLayoutManager(lm);
rv.setAdapter(new MyAdapter(this));
}
PS:
For lazy people like me maybe it's a simpler way rather than extending my custom LayoutManager
, But I'm sure there are better ways to achieve this.
Update:
Updated part of your question is more simpler, You can use GridLayoutManager
:
GridLayoutManager glm = new GridLayoutManager(this, 3);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (position % 3 == 2) {
return 3;
}
switch (position % 4) {
case 1:
case 3:
return 1;
case 0:
case 2:
return 2;
default:
//never gonna happen
return -1 ;
}
}
});
rv.setLayoutManager(glm);
In this way you set 3 for default span size, Then considering the position of your span, Each item occupies 1, 2 or 3 spans, Something like this:
Item0.width == 2 X Item1.width
Item2.width == 3 X Item1.width
Item0.width == 2/3 X Item1.width
这篇关于RecyclerView Grid的LayoutManager具有不同的单元宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!