0

TLDR:

Usually, in a RecyclerView implementation, between the Adapter and the LayoutManager, there is a one-view-per-item ratio. We are hoping to find a way to create multiple views per item.

Note: Please don't confuse this with being able to create different view types based on adapter position. For simplicity assume there is only one view type.

Full Question:

For our project, we need to create a multi-column list. A multi-column list is visually identical to a grid, but has one noticeable difference; in a grid (like that created with GridLayoutAdapter), one 'cell' (i.e. View/ViewHolder) represents one item. In a multi-column list, one row represents one item. The cells that make up that row each display different properties of that same, single item.

As an example, say I have a list of ten Foo objects, and Foo defines five properties which we want to display in columns. From the perspective of our dataset, there are ten items. From the perspective of the LayoutManager however, there are fifty (ten items (the rows) times five cells (the columns) per row/item.)

The approach I'm leaning to is to create a co-dependent RecyclerView.Adapter / RecyclerView.LayoutManager pair.

First, in my adapter subclass, in addition to creating a property to hold my data items, I also added a 'columnCount' property. Then in the getItemCount() override, rather than returning the number of items like one would normally do, I instead return the number of items multiplied by the columnCount, like so:

private List<Object> items;
public List<Object> getItems(){
    return items;
}
public void setItems(List<Object> items){
    this.items = items;
    notifyDataSetChanged();
}

private int columnCount = 1;
public int getColumnCount(){
    return columnCount;
}
public void setColumnCount(int columnCount){
    this.columnCount = Math.max(columnCount, 1);
    notifyDataSetChanged();
}

@Override public final int getItemCount(){
     return getItems().size() * getColumnCount();
}

Next in my RecyclerView.LayoutManager subclass, I configure it to grab the passed-in adapter, and if I can cast it to my specific adapter type, then I can get the number of columns and use that for my layout calculations. If it's not the right type of adapter, I just treat it as if there's only one column.

Now while this approach seems to work, it muddies up the API a little as getItemCount() no longer returns the count of actual items, but rather the count of views, which may be confusing to a user. (I wish they had named it getViewCount() instead.) It also means again, that LayoutManager only works with a specific Adapter type.

I had also considered making it look like multiple columns by using a horizontal LinearLayout to represent an entire row, then using that in a regular list, but that limited our flexibility (i.e. can't do fixed rows/columns, etc.) so we abandoned it.

I'm wondering if I'm approaching this wrong and/or if there's an API I can already use for this. Is there such a thing, or am I on the correct approach?

Mark A. Donohoe
  • 28,442
  • 25
  • 137
  • 286

2 Answers2

1

You can achieve this at the adapter level. You will have to use these three methods.

getItemViewType() 
onCreateViewHolder() 
onBindViewHolder()

Here is a working example for your help.Let me know if anything is not making sense. Just make your item a viewpager and add multiple pages of items.

https://guides.codepath.com/android/Heterogenous-Layouts-inside-RecyclerView

android_Muncher
  • 1,057
  • 7
  • 14
  • I don't think this addresses my question. Your suggestion is about using different view *types*. I'm talking about multiple *views* per item. In other words, if I have a class Foo that has five properties, and I want to display a list of ten Foo objects showing each of those five properties in their own column, those ten Foo items would require 50 total 'View/ViewHolders', five per item. Make sense? That's why I stated to do the adapter the way I said, but it's still not enough info as-is. I think I need a combination of custom Adapter/LayoutManager that have to specifically work together. – Mark A. Donohoe Oct 16 '17 at 05:03
  • @MarqueIV can you share a visual representation ? would you need to scroll between 5 properties of each item ? Do you need something like this ? https://github.com/lsjwzh/RecyclerViewPager – android_Muncher Oct 16 '17 at 05:13
  • Just think of a grid. In the example I described above, it would be a grid with ten rows and five columns. I originally thought of doing a single view per row (so essentially it's just a regular list at that point) and making that view *look* like multiple columns, but I specifically need to lay out the cells manually. For instance, the first column is fixed and doesn't scroll. Think of how a spreadsheet with fixed/frozen rows/columns works. Again though, each 'row' (all five views) are all tied to a single item. – Mark A. Donohoe Oct 16 '17 at 05:16
  • @MarqueIV why not use grid layout? – android_Muncher Oct 16 '17 at 05:24
  • Again, GridLayout means one item per cell. It's still a 1-to-1 ratio. 10 data items would manage ten views. I'm looking for, as an example, a 1-to-5 ratio. Ten data items = 50 views. I've updated the question to try and be more clear. – Mark A. Donohoe Oct 16 '17 at 05:26
  • In other words, if I added a single new item to my dataset, I would get an entire row of new views. If I defined my layout to be ten columns, I would get *ten* new views for that *single* item. – Mark A. Donohoe Oct 16 '17 at 05:29
0

You can have multiple view holders with different view's so based on type you can use different views.

Shanmugam
  • 301
  • 1
  • 10