具有不同单元格宽度的 RecyclerView Grid 的 LayoutManager [英] LayoutManager for RecyclerView Grid with different cell width
问题描述
StaggeredGridLayoutManager
似乎不允许自定义单元格宽度或跨多个列(全跨度除外)垂直方向.
如上所示,用于组织单元格的首选 LayoutManager
是什么?
P.S. 我只想知道如何使用 StaggeredGridLayoutManager
自定义单元格宽度 而不是高度.我知道可以自定义高度,如在这个
与 StaggeredGridLayoutManager
或任何其他布局管理器中的单元格 1 相比,如何增加单元格 0 的宽度?
你可以使用 StaggeredGridLayoutManager.LayoutParams
来改变单元格的宽度和高度,你期望设计的遵循一个简单的模式,如果你为每个单元格分配一个索引(按照 StaggeredGridLayoutManager
默认排列它们的顺序),您将拥有:
index % 4 == 3 --->全跨度单元格指数 % 8 == 0, 5 --->半跨单元索引 % 8 == 1, 2, 4, 6 --->四分之一跨度单元
首先在adapter中声明一些常量来定义span类型:
private static final int TYPE_FULL = 0;私有静态最终 int TYPE_HALF = 1;私有静态最终 int TYPE_QUARTER = 2;
然后像这样覆盖适配器中的 getItemViewType
方法:
@Override公共 int getItemViewType(int position) {最终 int modeEight = 位置 % 8;开关(模式八){案例0:案例5:返回 TYPE_HALF;情况1:案例2:案例4:案例6:返回类型_季度;}返回 TYPE_FULL;}
您需要做的就是考虑holder
的viewType
来更改layoutparams:
@Overridepublic MyHolder onCreateViewHolder(final ViewGroup parent, final int viewType) {最终视图 itemView =LayoutInflater.from(mContext).inflate(R.layout.items, parent, false);itemView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {@覆盖公共布尔 onPreDraw() {最终 int 类型 = 视图类型;最终 ViewGroup.LayoutParams lp = itemView.getLayoutParams();if (lp instanceof StaggeredGridLayoutManager.LayoutParams) {StaggeredGridLayoutManager.LayoutParams sglp =(StaggeredGridLayoutManager.LayoutParams) lp;开关(类型){案例 TYPE_FULL:sglp.setFullSpan(true);休息;案例 TYPE_HALF:sglp.setFullSpan(false);sglp.width = itemView.getWidth()/2;休息;案例类型_季度:sglp.setFullSpan(false);sglp.width = itemView.getWidth()/2;sglp.height = itemView.getHeight()/2;休息;}itemView.setLayoutParams(sglp);最终 StaggeredGridLayoutManager lm =(StaggeredGridLayoutManager) ((RecyclerView) parent).getLayoutManager();lm.invalidateSpanAssignments();}itemView.getViewTreeObserver().removeOnPreDrawListener(this);返回真;}});MyHolder holder = new MyHolder(itemView);退货持有人;}
我的适配器总是为项目计数返回 50(只是一个测试),我使用了一个简单的项目布局文件,它包含一个 LinearLayout
和一个 TextView
来显示持有人的位置,请记住,由于您的设计,您应该为 spanCount
(在 StaggeredGridLayoutManager
构造函数中)传递 2.
@Overrideprotected 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));}
附注:对于像我这样的懒人来说,这可能比扩展我的自定义 LayoutManager
更简单,但我相信有更好的方法来实现这一点.
更新:您问题的更新部分更简单,您可以使用 GridLayoutManager
:
GridLayoutManager glm = new GridLayoutManager(this, 3);glm.setSpanSizeLookup(新的GridLayoutManager.SpanSizeLookup(){@覆盖公共 int getSpanSize(int position) {如果(位置 % 3 == 2){返回3;}开关(位置 % 4){情况1:案例3:返回 1;案例0:案例2:返回2;默认://永远不会发生返回 -1 ;}}});rv.setLayoutManager(glm);
这样你把默认跨度大小设置为3,然后考虑你跨度的位置,每个项目占据1、2或3个跨度,像这样:
Item0.width == 2 X Item1.widthItem2.width == 3 X Item1.widthItem0.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屋!