Search code examples
androidandroid-recyclerviewandroid-chips

RecyclerView with dynamic elements based on response


I am tryin to create a RecyclerView which displays a list of cars along with various tags for each row item.

For example:

BMW

v6,turbo ---> Tags

Merc

V8, Twin-turbo, Carbon-Fiber ---> Tags

The problem being the tags are retrieved in a JSON response and can be of variable number. However, the title of the RecyclerView has only one textView at all times.

My current code has a simple RecyclerView where i am able to display the name of the various cars, however i am not sure how can i do a dynamic addition of the various tags below the fixed title based on the response.

Code:

 public class ListItemRecyclerViewAdapter extends RecyclerView.Adapter<ListItemRecyclerViewAdapter.ViewHolder>{
        private List<BaseItem> listOfItems = new ArrayList<>();
        private final List<TextView> textViewPool = new LinkedList<>();
        public ListItemRecyclerViewAdapter(List<BaseItem> listItems){

        }
        @NonNull
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View view = LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.fragment_list_item, parent, false);
            return new ViewHolder(view);
        }

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

        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            holder.carName.setText(((NewsItem)listOfItems.get(position)).getCar());


           Categories categories = ((ListItem)listOfItems.get(position)).getCategories();
           List<String> categoriesList = categories.getCategories();
            holder.bindViewForChips(categoriesList);
        }



        @Override
        public void onViewRecycled(@NonNull NewsViewHolder holder) {
            super.onViewRecycled(holder);
            holder.recycleTextViews();
        }

        // Clean all elements of the recycler
        private void clear() {
            listOfItems.clear();
        }

        public void addAll(List<BaseItem> list) {
            clear();
            listOfItems.addAll(list);
            notifyDataSetChanged();
        }

  class ViewHolder extends RecyclerView.ViewHolder{

        @BindView(R.id.car)
        TextView carName;

        private final List<TextView> textViews = new ArrayList<>();
        private final ViewGroup container;

        ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this,itemView);
            container = (ViewGroup) itemView;
        }

        private void bindViewForChips(List<String> categories){
            recycleTextViews();
            for (int i = 0; i < categories.size(); i++) {
                final TextView textView = getRecycledTextViewOrCreate();
                textViewPool.add(textView);
                container.addView(textView);
            }
        }

        private TextView getRecycledTextViewOrCreate() {
          //  if (textViewPool.isEmpty()) {
                return (TextView)LayoutInflater.from(container.getContext()).inflate(R.layout.chips_view, container, false);
            //}
            //return textViewPool.remove(0);
        }

        public void recycleTextViews() {
            textViewPool.addAll(textViews);
            textViews.clear();
            container.removeAllViews();
        }
    }
    }

Any help is appreciated. Thanks!


Solution

  • IMO it depends somewhat on your UI as well. If you just want to show tags in comma separated format, you can loop through the tags array and create a string using StringBuilder and assign it to a TextView.

    You can also use recyclerView inside recyclerView, but I think that could be an overkill for this situation. You can go for this option if tags are going to be clickable. This way you can style each tag element as well. Or maybe a staggered list could also look good.

    Option 1: Show all tags in a single TextView. In that case your list item xml will be like this.

    <TextView>BMW</TextView>
    <TextView>ConcatenatedTagsFromArray</TextView>
    

    Option 2: Show tags in a child RV. In that case parent list item xml will be like this.

    <TextView>BMW</TextView>
    <recyclerView>childRecyclerViewID</recyclerView>
    

    And then create a recyclerview object inside onBindViewHolder method of parent RV and set layout manager and adapter and pass tags array as data. You will also need a new list item xml for child recycler view's items(However you want your tag to look like).