3

I've a list of following model:

name
categoryName

Now, I've to build a recyclerview that groups all the entities with the same categoryName:

categoryName1
    name1
    name2
    name3
categoryName2
    name4
categoryName3
    name5
    name6

So I have two different row type (different styles). The list is ordered. I don't necessary need the code, but, what's the algorithm to use for the adapter? Can I solve this with only one cycle?

I'd like to avoid adding view to a vertical LinearLayout from code.

Jumpa
  • 4,319
  • 11
  • 52
  • 100
  • Take a look at https://stackoverflow.com/questions/26245139/how-to-create-recyclerview-with-multiple-view-type – Jorge E. Hernández Nov 16 '17 at 14:43
  • I've read that answer, but when i attach the list to the adapter and it cycles my list, I don't have two different types of object. So if a render a categoryName, this means I'll skip a name. – Jumpa Nov 16 '17 at 14:50

2 Answers2

4

Your data should look like this:

public class CategorizedName {

    private Category category;
    private Collection<Name> names = null;

    public Category getCategory() {
        return category;
    }

    public Collection<Name> getNames() {
        return names;
    }

    // override hashCode and equals ...
}

In your adapter you should do something like this:

private static final int CATEGORY = 1;
private static final int NAME = 2;    

private Collection<CategorizedName> data;

@Override
public int getItemViewType(int position) {
    if (items.get(position) instanceof Category) {
        return CATEGORY;
    } else if (items.get(position) instanceof Name) {
        return NAME;
    }
    throw new RuntimeException('error');
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {

    RecyclerView.ViewHolder viewHolder;
    LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());

    switch (viewType) {
        case CATEGORY:
            View categoryView = inflater.inflate(R.layout.viewholder_category, viewGroup, false);
            viewHolder = new CategoryViewHolder(categoryView);
            break;
        case NAME:
            View nameView = inflater.inflate(R.layout.viewholder_name, viewGroup, false);
            viewHolder = new NameViewHolder(nameView);
            break;
    }
    return viewHolder;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
      switch (viewHolder.getItemViewType()) {
          case USER:
              CategoryViewHolder categoryViewHolder = (CategoryViewHolder) viewHolder;
              bindCategoryViewHolder(categoryViewHolder, position);
              break;
          case IMAGE:
              NameViewHolder nameViewHolder = (NameViewHolder) viewHolder;
              bindNameViewHolder(nameViewHolder, position);
              break;
      }
}

Don't forget to create view holders.

EDIT 1: added data structure for adapter

TheKarlo95
  • 1,144
  • 9
  • 17
  • At the moment I've a unique list of the model i described above. So should I use a temp data structure to save category ---MANY-> names? – Jumpa Nov 16 '17 at 15:03
  • @Jumpa I eddited answer. Hope that resolves your question. – TheKarlo95 Nov 16 '17 at 15:18
  • I've upvoted your answer, thanks for your time. Anyway I still wondering if I can do that without a support data structure. – Jumpa Nov 16 '17 at 15:20
  • @Jumpa Of course you can. You just need method like Collection getAllNames(Category category). All you need to do is implement logic that connects category to names and probably sort it how you seem fits best. – TheKarlo95 Nov 16 '17 at 15:22
1

You must override method public int getItemViewType(int position) of RecyclerView, and handle it in public void onCreateViewHolder(ViewGroup parent, int viewType)

Example:

enum Type{Name,Category}

@Override
public int getItemViewType(int position) {
   if (position == POSITION_CATEGORY_1 || position == POSITION_CATEGORY_2) {
      return Type.Category;
   } else {
      return Type.Name;}
   }
}

End bind:

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if(viewType == Type.Category.ordinal()){
        return new CategoryItemView(...);
    }else {
        return new CommonItemView(...);
    }
}
Alexey Zatsepin
  • 1,179
  • 7
  • 14