0

I have no problem creating multiple view holders in a recyclerview. The problem I am having it determining the positioning the the headers and items.

I am creating a gallery app and I want to have my album names as headers and put 8 images for each album. So you would have a header with album title then 8 pictures from that album. then the next header with album title and 8 pictures from that album. And continue on with that scheme. If there is less than 8 pictures i want to leave those blank until the next header would start.

I have two ArrayList i am getting my data from. Albums and Media.

I am trying to set the type in getItemViewType of my adapter but can't figure out how to set them like mentioned above. Whats confusing me is trying to set position with multiple arraylist and unknown number of pictures for each album.

Again this is not another question like the many I have seen about setting up multiple view holders in a recyclerview. I have that concept. My problem is determining positioning for the view holders.

This is how my create and bind views look to give some context

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == ALBUM_TYPE) {
        return new AlbumHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.card_view, parent, false));
    } else if (viewType == HEAD_TYPE) {
        return new HeadHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.header_text, parent, false));
    } else {
        return new MediaHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.card_photo, parent, false));
    }

}

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof AlbumHolder) {
        Album m = albums.get(position);
        ((AlbumHolder)holder).bindView(m, position);
    } else if (holder instanceof HeadHolder) {
        if (sortingMode == SortingMode.FOLDER) {
            Album m = albums.get(position);
            ((HeadHolder)holder).bindView(m.getName(), position);
        } else {
            String m = sortListYear.get(position);
            ((HeadHolder)holder).bindView(m, position);
        }

    } else {
        Media m = media.get(position);
        ((MediaHolder)holder).bindView(m, position);
    }

}

The ALBUM_TYPE is not used for this question I am asking. Just the HEAD_TYPE AND MEDIA_TYPE.

BigDX
  • 3,519
  • 5
  • 38
  • 52

2 Answers2

0

Consider 2 objects here Media and Head

What you can do is create another ArrayList and add the data(Media or Head) in this new arraylist(Object) in sequence as you want it to be displayed/used in the recyclerview.

ArrayList<Object> objList = new ArrayList<>();
objList.add(new Head("Header1");
objList.add(new Media("/img1"));
objList.add(new Media("/img2"));
objList.add(new Media());//no image, for blank entry
objList.add(new Head("Header2"));
objList.add(new Media("/img3"));
objList.add(new Media());
objList.add(new Media());

Now you can use instanceof in getItemViewType . Here position is decided by the index of objList.

singhnikhil
  • 670
  • 5
  • 7
  • I like this approach but I am struggling to create the objList. I am trying a nested loop but can't seem to make it work. any tips on how it would look. My media has a method to see what album(head) it belongs to. – BigDX Aug 23 '17 at 13:38
  • can you share some code on how you are trying to create objList?That way it would be easier to suggest . – singhnikhil Aug 23 '17 at 19:05
0

You have two separate ArrayList for media and album.

 ArrayList<Object> mediaList = new ArrayList();

ArrayList<Object> albumList = new ArrayList();

In your scenario you need to calculate the position.

Lets fix this with a example. In your getItemViewType method you have set media is to be in the first set of list followed by album.i.e., total recyclerview size is 10 in that first 8 rows will be media and last two rows will be album.

@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
int currentPosition = 0;
if ((mediaList.size() - 1) >= position) {
//Since media list is loaded first...
    currentPosition = position;
} else {
    //Since we are loading the album next we need to take from here...
   currentPosition = position - mediaList.size();
}


 if (holder instanceof MediaHolder) {
        Media m = media.get(currentPosition);
        ((MediaHolder)holder).bindView(m, currentPosition);
    } else if (holder instanceof AlbumHolder) {
        Album m = albums.get(currentPosition);
        ((AlbumHolder)holder).bindView(m, currentPosition);
    }

}

If you got any ArrayIndexOutOfBound Exception in the below line,

currentPosition = position - mediaList.size();

kindly do the below change,

currentPosition = (position - mediaList.size()) - 1;

For more info you can refer this link, in this example we have implemented a footer and for that also I have calculated the position.

Hope this is helpful:)

Jeevanandhan
  • 1,073
  • 10
  • 18
  • Can't seem to figure out what the getItemViewType method will look like to make this work. Also it would be 8 media per album. You say "total recyclerview size is 10 in that first 8 rows will be media and last two rows will be album" which would not be correct. if last two rows would be album then there should be 16 media rows. – BigDX Aug 23 '17 at 13:36