János
János

Reputation: 35060

Possible do define sections in RecyclerView in Android?

In iOS UITableView could have 'sections' and inside a section 'rows'. Is this possible in Android with RecycleView?

RecyclerView.Adapter has only a getItemCount() delegate method. But nothing for sections. What alternatives you can suggest?

I thought to put the section headers into a row, and melt the sections into one global section, and so no section will need. Any better idea?

Upvotes: 0

Views: 1441

Answers (2)

pawelo
pawelo

Reputation: 1415

RecyclerView.Adapter supports multiple view types out of the box. It's up to you which item type you want to display at any particular position. You can easily use it to create sections, for example if you define two item types TYPE_HEADER and TYPE_ITEM:

@Override
public int getItemViewType(int position) {
    if (isHeader(position)) {
        return TYPE_HEADER;
    } else {
        return TYPE_ITEM;
    }
}

Then, you can use onCreateViewHolder to inflate proper layouts and onBindViewHolder to make use of it.

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == TYPE_HEADER) {
        View v = ... ; // inflate here
        return new HeaderViewHolder(v);
    } else {
        View v = ... ; // inflate here
        return new ItemViewHolder(v);
    }    
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
    if (holder instanceof HeaderViewHolder) {
        // handle header
    } else if (holder instanceof ItemViewHolder {
        // handle item
    }
}

The only thing left is data structure to keep stuff. There are many ways to implement it and I think it's a little bit out of the scope of your question. If data structure is very deep I prefer using custom tree-like structure I made some time ago but sometimes I use flat List and check item types using instanceof.

Upvotes: 1

Nikhil
Nikhil

Reputation: 3711

Override getItemViewType() method to return Type of your section. And in onCreateViewHolder() method inflate your layout according to type.

finally in onBindViewHolder() method render your views according to the type again

following is dummy RecyclerViewAdapter that may help you

class CustomRecyclerViewAdapter extends RecyclerView.Adapter<CustomRecyclerViewAdapter.ViewHolder> {
        public final int NEWS_LAYOUT = 0;
        public final int ARTICLE_LAYOUT = 1;
        public final int PROGRESS_BAR_LAYOUT = 2;
        ArrayList<YourModel> list;
        Context context;

        public CustomRecyclerViewAdapter(Context context) {
            this.context = context;
        }

        @Override
        public CustomRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                                       int viewType) {

            ViewHolder vh = null;
            View v;
            switch (viewType) {
                case NEWS_LAYOUT:
                    v = LayoutInflater.from(parent.getContext())
                            .inflate(R.layout.layout_card_view, parent, false);
                    vh = new ViewHolder(v, viewType);
                    break;
                case ARTICLE_LAYOUT:
                    v = LayoutInflater.from(parent.getContext())
                            .inflate(R.layout.layout_card_view, parent, false);
                    vh = new ViewHolder(v, viewType);
                    break;
                case PROGRESS_BAR_LAYOUT:
                    v = LayoutInflater.from(parent.getContext())
                            .inflate(R.layout.progress_bar, parent, false);
                    vh = new ViewHolder(v, viewType);
                    break;
                default:
                    break;
            }
            return vh;
        }

        @Override
        public void onBindViewHolder(ViewHolder holder, int position) {
            try {
                //assign data according to your types
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public int getItemCount() {
            return list.size();
        }


        public void addAll(List list) {
            if (null == this.list)
                this.list = new ArrayList<>(;
            else {
                this.list.addAll(list);
            }
        }

        public void clear() {
            list.clear();
        }

        @Override
        public int getItemViewType(int position) {
                if (list.get(postion).getType().equals("News Layout")) {
                    return NEWS_LAYOUT;
                } else if (list.get(postion).getType().equals("Article Layout")) {
                    return ARTICLE_LAYOUT;
                } else if (list.get(postion).getType().equals("progressbar"))
                    return PROGRESS_BAR_LAYOUT;
                }
            return -1;
        }

        public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
            public CardView cardView;
            public ProgressBar progressBar;

            public ViewHolder(View view, int type) {
                super(view);
                if (type == NEWS_LAYOUT || type == ARTICLE_LAYOUT) {
                    this.cardView = (CardView) view.findViewById(R.id.card_view);
                    this.cardView.setOnClickListener(this);
                } else if (type == PROGRESS_BAR_LAYOUT) {
                    this.progressBar = (ProgressBar) view.findViewById(R.id.recycler_view_progress_bar);
                }
            }

            @Override
            public void onClick(View view) {
                //perform operations
            }
        }
    }

Upvotes: 0

Related Questions