android - 具有不同单元格宽度的 RecyclerView Grid 的 LayoutManager

标签 android gridview android-recyclerview

StaggeredGridLayoutManager 似乎不允许自定义 单元格宽度 或跨越多个列(全跨度除外)以实现垂直方向。

enter image description here

如上所示用于组织单元格的首选 LayoutManager 是什么?

P.S. 我只想知道如何使用 StaggeredGridLayoutManager 自定义 单元格宽度 而不是高度。我知道高度可以按照 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();
    }
}

适配器

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) 不影响单元格宽度。

为了简化,我将网格布局更新为

enter image description here

StaggeredGridLayoutManager 或任何其他布局管理器中的单元格 1 相比,如何增加单元格 0 的宽度?

最佳答案

您可以使用 StaggeredGridLayoutManager.LayoutParams 来更改单元格的宽度和高度,您期望的设计遵循一个简单的模式,如果您为每个单元格分配一个索引(按照 StaggeredGridLayoutManager 默认排列它们)你会得到这个:

index % 4 == 3           --->  full span cell
index % 8 == 0, 5        --->  half span cell
index % 8 == 1, 2, 4, 6  ---> quarter span cell

首先在adapter中声明一些常量来定义span类型:

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;
        case 1:
        case 2:
        case 4:
        case 6:
            return TYPE_QUARTER;
    }
    return TYPE_FULL;
}

您需要做的就是考虑 holderviewType 更改布局参数:

@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;
}

我的适配器总是返回 50 的项目计数(只是一个测试),我使用了一个简单的项目布局文件,它包含一个 LinearLayout 和一个 TextView 来显示持有人的位置,请记住,由于您的设计,您应该为 spanCount (int the StaggeredGridLayoutManager 构造函数)传递 2。

@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));

}

enter image description here

附言: 对于像我这样的懒人来说,这可能是一种更简单的方法,而不是扩展我的自定义 LayoutManager,但我确信有更好的方法来实现这一点。

更新: 您的问题的更新部分更简单,您可以使用 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);

通过这种方式,您将默认跨度大小设置为 3,然后考虑跨度的位置,每个项目占用 1、2 或 3 个跨度,如下所示:

enter image description here

Item0.width == 2 X Item1.width
Item2.width == 3 X Item1.width
Item0.width == 2/3 X Item1.width

关于android - 具有不同单元格宽度的 RecyclerView Grid 的 LayoutManager,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36514887/

相关文章:

android - 从 Google 云端硬盘文件中读取文本

android - 如何显示带有进度微调器的对话框?

android - 适用于 ARM 的示例 Android BSP(源代码)

java - 具有不同 GridView 的可滚动选项卡

java - GridView 行为不正确

asp.net - 通过 jQuery ajax 绑定(bind) GridView

javascript - Android 互联网应用程序无法正确呈现移动网站版本

Android Recycler (List) View 展开转场动画

android-layout - RecyclerView SCROLL_STATE_IDLE 被延迟调用

java - 将数据传递到 RecyclerView 适配器