RecyclerView Grid的LayoutManager具有不同的单元宽度 [英] LayoutManager for RecyclerView Grid with different cell width

查看:254
本文介绍了RecyclerView Grid的LayoutManager具有不同的单元宽度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆