在LinearLayoutManager内部使用GridLayoutManager的RecyclerView

3

我基本上正在尝试实现这个设计原则(来自Google的Material Design): enter image description here 因此,我创建了一个带有LinearLayoutManager的父RecyclerView,然后在RecyclerView适配器中,我放置了一个带有GridLayoutManager的子RecyclerView,用于“丰富媒体”部分(操作区域2)。一切都运行正常,除了一个问题:我将内部RecyclerView网格设置为具有match_parent宽度和wrap_content高度,但它不会正确计算内容的大小,似乎将其保留为0,因此隐藏。如果我将子RecyclerView设置为特定高度,则其中的项目将显示,但当然在底部被截断。 其他人似乎遇到了这个问题,但在他们的情况下,两者都有线性布局。(也请参见{{link4:“Khay”的答案在此处}}。)
现在我的问题是,如何在自定义的GridLayoutManager中覆盖onMeasure方法,就像链接问题中“pptang”在被接受的答案中所做的那样,而不是在自定义的LinearLayoutManager中?我没有在这里发布我的代码,因为它与链接的代码基本相同,只是我需要为子RecyclerView创建一个自定义的GridLayoutManager,以便它能够按照“pptang”的答案正确地测量。

否则,有没有比使用第二个RecyclerView内部的1个RecyclerView更好的方法?只有一个RecyclerView可以用上面的CardViews列表和每个CardView中唯一项目的网格填充活动/片段吗?


根据材料设计指南,“将补充操作限制为两个操作”。您想在父列表中添加多少项?滚动条如何工作?网格和列表都使用垂直滚动吗? - masp
我想要有几个ViewPager选项卡,一个包含3个父级CardView,另一个可能有8个父级CardView,还有一个包含大约5个父级CardView。这些格子完全“开放”,因此没有内部滚动,只有父级CardView可以垂直滚动。根据我的观察,将一个RecyclerView放到另一个RecyclerView中也会影响到工具栏的隐藏(CoodinatorLayout),如果您尝试通过保持RecyclerView网格来滚动,则工具栏不会隐藏,但仅当你在子RecyclerView之外的地方按住时才会隐藏。 - inferKNOX
我觉得我可能偏离了你实际询问的问题@masp。抱歉。在每个“CardView”中,我只想在顶部放置标题和图标,在中心放置网格,并添加一个“展开器”来隐藏一些支持文本。可能还可以使“CardView”的标题部分具有隐藏/折叠和显示/展开网格的功能,就像“ExpandableListView”一样。 - inferKNOX
你说:“网格的意图是完全“开放”的,因此没有内部滚动,只有父CardViews可以垂直滚动。” 这意味着您不需要在Recycler View中再嵌套一个Recycler View。一个GridLayout Manager就足够了。我还没有尝试Gustavo建议的内容,所以我不知道它是否涵盖了您所要求的所有内容,但它确实朝着正确的方向发展。 - masp
最佳方式 - 使用任何库,例如RendererRecyclerViewAdapter,请查看CompositeViewRenderer。另外,请参考此答案https://dev59.com/41wY5IYBdhLWcg3w9rza#48464993 - Vitaly
显示剩余3条评论
2个回答

3
您可以使用库SectionedRecyclerViewAdapter只使用一个RecyclerView来构建它。

您可以在此处找到下面图片示例的完整代码

enter image description here

首先创建一个Section类:

class MySection extends StatelessSection {

    String title;
    String subtitle;
    List<String> list;

    public MySection(String title, String subtitle, List<String> list) {
        // call constructor with layout resources for this Section header, footer and items 
        super(R.layout.section_header, R.layout.section_item);

        this.title = title;
        this.subtitle = subtitle;
        this.list = list;
    }

    @Override
    public int getContentItemsTotal() {
        return list.size(); // number of items of this section
    }

    @Override
    public RecyclerView.ViewHolder getItemViewHolder(View view) {
        // return a custom instance of ViewHolder for the items of this section
        return new MyItemViewHolder(view);
    }

    @Override
    public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
        MyItemViewHolder itemHolder = (MyItemViewHolder) holder;

        // bind your view here
        itemHolder.tvItem.setText(list.get(position));
    }

    @Override
    public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
        return new SimpleHeaderViewHolder(view);
    }

    @Override
    public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
        MyHeaderViewHolder headerHolder = (MyHeaderViewHolder) holder;

        // bind your header view here
        headerHolder.tvTitle.setText(title);
        headerHolder.tvSubTitle.setText(subtitle);
    }
}

然后,您可以使用您的部分设置RecyclerView:
// Create an instance of SectionedRecyclerViewAdapter 
SectionedRecyclerViewAdapter sectionAdapter = new SectionedRecyclerViewAdapter();

// Create your sections with the list of data for each year
MySection section1 = new MySection("Title", "Subhead", firstDataList);

// Add your Sections to the adapter
sectionAdapter.addSection(section1);

// Set up your RecyclerView with the SectionedRecyclerViewAdapter
GridLayoutManager glm = new GridLayoutManager(getContext(), 2);
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
    @Override
    public int getSpanSize(int position) {
        switch(sectionAdapter.getSectionItemViewType(position)) {
            case SectionedRecyclerViewAdapter.VIEW_TYPE_HEADER:
                return 2;
            default:
                return 1;
        }
    }
});
recyclerView.setLayoutManager(glm);
recyclerView.setAdapter(sectionAdapter);

1
我理解你的意思,那实际上就是我之前做过的事情,从这里学到了。但这不是我想要的,我真正想要的是将CardView作为一个部分,内部的元素就像Google自己所演示的那样,并且这些CardViews本身也在一个RecyclerView中。如何实现与Google一样的结果? - inferKNOX
有一个更简单的库可以支持带有自定义布局管理器的嵌套RecyclerView RendererRecyclerViewAdapter,请查看CompositeViewRenderer。另外,请参考这个答案https://dev59.com/41wY5IYBdhLWcg3w9rza#48464993。 - Vitaly

0
总结一下,你不应该在一个Recycler内部使用另一个Recycler。你需要实现一个自定义的GridLayoutManager。为了实现这个,请阅读以下内容:
从文档中可以看到https://developer.android.com/reference/android/support/v7/widget/RecyclerView.ItemDecoration.html ItemDecoration允许应用程序向适配器数据集中的特定项视图添加特殊的绘制和布局偏移量。这对于在项目之间绘制分隔线、高亮显示、可视化分组边界等非常有用。
因此,如果你使用上述方法以及这个http://blog.sqisland.com/2014/12/recyclerview-grid-with-header.html,你肯定可以实现你想要的效果。只需将你从材料指南中呈现的图像视为网格布局管理器中的一个组即可。
  • 你可以拥有不同类型的视图
  • 每行可能有多个视图
  • 每行可能会被装饰得不同

1
我理解你的意思并同意RecyclerView内部嵌套RecyclerView是不正确的。然而,将它们分组只会实现与上述类似的结果,而不是相同的结果,因为那是一个真正的CardView,而不仅仅是一种分组。问题变成了,我们如何将其从简单的分组转换为真正的CardViews - inferKNOX

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接