使用网格布局在RecyclerView上实现标头的最佳方法?

问题描述:

我想实现下面的图像。我的第一个想法是将网格布局上方的所有内容作为网格的第一行,并使用SpanSizeLookup将跨度大小设置为RecyclerView中的列数,但这感觉像是会给我带来很多问题的东西。使用网格布局在RecyclerView上实现标头的最佳方法?

我一直在阅读关于在NestedScrollView中放置一个RecyclerView,人们说它的工作原理,但我似乎无法让它正常工作。滚动似乎没有工作正确,我不能让网格甚至没有设置minHeight显示,但它看起来很糟糕。

有没有另一种选择,我不考虑或是我应该去的这些方向之一?

Here's what I'm trying to achieve

+0

为什么你需要一个嵌套的滚动视图?这是FAB吗? – Droidekas

+0

因为我不想只是网格滚动,我希望整个事情滚动。如果网格只是线性布局下的回收站,那么线性布局将始终在屏幕上,而您只需在底部滚动一个小网格即可。我希望它能像Instagram一样工作。 – jmickela

+0

然后使linearlayout成为网格视图的一部分?如果您确定不会有太多的页眉/页脚,您应该检查书挡。 – Droidekas

您希望从SpanSizeLookup得到什么样的问题?你可以用如下几行来实现它(我建议使用来自integers.xml的值来提高灵活性)。

GridLayoutManager glm = new GridLayoutManager(getContext(), 3); 
glm.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { 
    @Override public int getSpanSize(int position) { 
     return (position == 0) ? 3 : 1; 
    } 
}); 

如果你的头布局需要的意见和领域,你的常规布局不有,你要创建单独的意见,并告诉您的适配器他们。像这样的东西。

@Override 
public int getItemViewType(int position) { 
    if (position == 0) 
     return TYPE_HEADER; 
    else 
     return TYPE_REGULAR; 
} 

@Override 
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    if (viewType == TYPE_HEADER) { 
     MyHeaderView view = (MyHeaderView) LayoutInflater 
       .from(parent.getContext()) 
       .inflate(R.layout.my_header_view, parent, false); 
     return new MyHeaderViewHolder(view); 
    } else { 
     MyRegularView view = (MyRegularView) LayoutInflater 
       .from(parent.getContext()) 
       .inflate(R.layout.my_regular_view, parent, false); 
     return new MyRegularViewHolder(view); 
    } 
} 

一个例子标题视图可以是这样的(你会打电话bindTo()MyHeaderViewHolder)。

public final class MyHeaderView extends LinearLayout { 
    @Bind(R.id.image) ImageView imageView; 
    @Bind(R.id.title) TextView titleView; 

    public MyHeaderView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    @Override 
    protected void onFinishInflate() { 
     super.onFinishInflate(); 
     ButterKnife.bind(this); 
    } 

    public void bindTo(String imageUrl, String title) { 
     Glide.with(getContext()) 
       .load(imageUrl).into(imageView); 
     titleView.setText(title); 
    } 
} 
+0

是否可以在不更改适配器的情况下添加标题?也许使用NestedScrollView? –

+0

这就是我最终做的,并没有真正有任何问题。 – jmickela

+0

我在一些应用程序中使用了这种方法,到目前为止效果很好。我想我从[u2020 app](https://github.com/JakeWharton/u2020)得到了一般想法。但我同意你最初的担忧。在不同的文件中使用这么多的代码会感觉错误,并且会使测试变得更加困难。 – Jimeux

  1. 你可以看看Bookends

  2. 或者另一个(这样我通常这样做)的方法是使用GridLayouManager用SpanSizeLookUp。并使用多个ViewTypes,即一个用于Header,Footer和Items。

转到1如果你只有一个头,并在你的代码有什么的ListView十岁上下接口。

如果您不确定要添加多少个Custom ViewType,请转到2。它可以确保您在将来具有最大的可扩展性。

如果您正在考虑大规模的可扩展性,我建议您阅读Hannes Dorfman的this article

这使得项目一样宽RecyclerView本身(类似于match_parent)。

在负责该项目的特定ViewHolder中设置各种点击监听器。使用这种方法会将整个复杂视图设置为RecyclerView的一部分(滚动),同时仍然使其可用于(输入)事件。

+1

谢谢我的朋友......我一直在寻找这个好几天。 – Vicky