9

I'm trying to implement the below image. My first thought was to have everything above the grid layout be the first row of the grid and use SpanSizeLookup to set the span size to the number of columns in the RecyclerView, but this feels like something that will give me a lot of problems.

I've been reading about putting a RecyclerView inside a NestedScrollView, people say it works, but I can't seem to get it to work properly. The scrolling doesn't seem to work right, I can't get the grid to even show up without setting a minHeight, but then it just looks bad.

Is there another option I'm not considering or is one of these the direction I should be going?

Here's what I'm trying to achieve

5
  • Why do you need a nested scrollview? is it for the FAB? Commented Nov 7, 2015 at 6:34
  • Because I don't want just the grid to scroll, I want the entire thing to scroll. If the grid is just a recyclerview below a linearlayout then the linearlayout will always be on the screen and you're just scrolling a small grid on the bottom. I want it to work similar to how Instagram does. Commented Nov 7, 2015 at 6:39
  • Then make the linearlayout a part of the grid view?You should check bookends if you are sure that you wont have too many headers/footers. Commented Nov 7, 2015 at 6:40
  • That's one of the options I'm considering, but it spreads what would normally be fairly simple code across several files. It just feels like overkill. Commented Nov 7, 2015 at 6:43
  • How comfortable are you with RecyclerView.If you are ,then Jimeux's answer is the best approach.You would have only 2 files,(3 including the bookend lib) . I think thats a fair number of files for such an interface. Commented Nov 7, 2015 at 6:48

3 Answers 3

22

What kind of problems are you anticipating from SpanSizeLookup? You can implement it with a few lines as follows (I'd recommend using values from integers.xml for flexibility).

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

If your header layout needs views and fields that your regular layout doesn't have, you'll want to create separate views and tell your adapter about them. Something like this.

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

An example header view could be like this (you'd call bindTo() from 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); } } 
Sign up to request clarification or add additional context in comments.

4 Comments

Is it possible to add a header, without changing the adapter? Maybe using NestedScrollView?
This is what I wound up doing and haven't really had any issues.
I've used this approach in a few apps, and it's worked well so far. I think I got the general idea from the u2020 app. I agree with your initial concerns though. Something feels wrong about having so much code in different files, and it makes testing more difficult.
This is the solution I originally went with but I'm having trouble with drag and drop functionality. When dragging between two different item view types, Android immediately drops the item being dragged. Is there a workaround for this?
3

This makes the item as wide as the RecyclerView itself (similar to match_parent).

Set various click listeners in the specific ViewHolder that's responsible for this item. Using this approach would set the whole complex view to behave (scroll) as part of the RecyclerView while still making it available for (input) events.

1 Comment

Thanks my friend... I've been looking for this for days.
1
  1. You could have a look at Bookends

  2. Or another(the way i usually do it) way would be to use a GridLayouManager with a SpanSizeLookUp. And use multiple ViewTypes i.e. one for Header,Footer and Items.

Go for 1 if you have only a single header and what a ListView-ish interface in your code.

Go for 2 if you are not sure about how many Custom ViewTypes you would be adding.It assures you have maximum scalability in the future.

If you are considering massive scalability,I suggest you read this article by Hannes Dorfman .

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.