How to use data for RecyclerView adapter and split them into different groups by parameter?

Viewed 3395

I'm working on RecyclerView, which will display data of same type (same Object) but each of those objects has to be in different ViewGroup. For example objects have 3 types. Each type will be separate list of objects (Group similar to Contact list in phone in alphabetical order).

I saw some posts about this issues, but they are using TreeMaps to separate data, but I'm not sure how to apply it to my problem. I have Header object which will be displayed over each group of data and Data object. What I need to do is to add 3 separate groups in one List and post it to adapter.

Also if I modify this item I can change it's type, so I will have to rearrange those data every time i modify an item. There is example down below how this RecyclerView should looks like (on display and order of items in a adapter list)

Example:

Header1
Itemtype1
Itemtype1
Itemtype1
Itemtype1
Header2
Itemtype2
Itemtype2
Header3
Itemtype3
Itemtype3
2 Answers

I have used Nested RecyclerView for this purpose.

Maybe not the best technique to achieve such layout. But it works somehow

MainActivity.xml (Headers)

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout     
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context=".Activities.MainActivity">

<android.support.v7.widget.RecyclerView
    android:id="@+id/rvMain"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:listitem="@layout/row"
    />

</android.support.constraint.ConstraintLayout>

MainActivity.java inside onCreate() (Headers)

    rvMain = findViewById(R.id.rvMain);
    ArrayList<Row> dataList = new ArrayList<>();
    myAdapter = new RowAdapter(MainActivity.this, dataList);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
    rvMain.setLayoutManager(layoutManager);
    rvMain.addItemDecoration(new DividerItemDecoration(MainActivity.this, LinearLayoutManager.VERTICAL));
    rvMain.setAdapter(myAdapter);

Row for MainActivity RecyclerView

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   xmlns:tools="http://schemas.android.com/tools"
   xmlns:app="http://schemas.android.com/apk/res-auto"
   android:padding="11dp">

<TextView
    android:id="@+id/tvAlbumNumber"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="Album 1"
    android:textColor="#000"
    android:textSize="21sp"
    android:textStyle="bold"
    android:typeface="monospace"
    />

<android.support.v7.widget.RecyclerView
    android:id="@+id/rvAlbums"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_below="@+id/tvAlbumNumber"
    android:layout_marginTop="3dp"
    tools:listitem="@layout/row_albums"
    />

</RelativeLayout>

* I put RecyclerView insied Row to have multiple items in it.

MainActivity RowAdapter

public class RowAdapter extends RecyclerView.Adapter<RowAdapter.ViewHolder>{
   public  ArrayList<Row> arrayList;
   public Context context;
   int albumPos;

public RowAdapter(Context context, ArrayList<Row> arrayList) {
    this.arrayList = arrayList;
    this.context = context;
}

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

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
    holder.tvAlbumNumber.setText("Album "+arrayList.get(position).getAlbumId());

    AlbumAdapter myAlbumAdapter = new AlbumAdapter(context, arrayList.get(position).getData());
    holder.rvAlbums.setLayoutManager(new LinearLayoutManager(context));
    holder.rvAlbums.setItemAnimator(new DefaultItemAnimator());
    holder.rvAlbums.addItemDecoration(new DividerItemDecoration(context,LinearLayoutManager.VERTICAL));
    holder.rvAlbums.setAdapter(myAlbumAdapter);
}

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

class ViewHolder extends RecyclerView.ViewHolder {
    TextView tvAlbumNumber;
    RecyclerView rvAlbums;

    public ViewHolder(View itemView) {
        super(itemView);
        tvAlbumNumber = itemView.findViewById(R.id.tvAlbumNumber);
        rvAlbums = itemView.findViewById(R.id.rvAlbums);
    }
  }
}

Inside onBindViewHolder I called the RecyclerView to fill the items in first header

Items Adapter (AlbumAdapter) (Items)

public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.AlbumViewHolder> {
    public ArrayList<RowAlbums> arrayList;
    private Context context;

AlbumAdapter(Context context, ArrayList<RowAlbums> arrayList) {
    this.context = context;
    this.arrayList = arrayList;
}

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

@Override
public void onBindViewHolder(@NonNull AlbumViewHolder holder, int position) {
    Picasso.get().load(arrayList.get(position).getImgUrl())
            .placeholder(R.drawable.user).error(R.drawable.user).into(holder.imgUser);
    holder.tvId.setText(arrayList.get(position).getId());
    holder.tvTitle.setText(arrayList.get(position).getTitle());
}

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

class AlbumViewHolder extends RecyclerView.ViewHolder {
    TextView tvId, tvTitle;
    ImageView imgUser;

    public AlbumViewHolder(final View itemView) {
        super(itemView);
        tvId = itemView.findViewById(R.id.tvId);
        tvTitle = itemView.findViewById(R.id.tvTitle);
        imgUser = itemView.findViewById(R.id.imgUser);

        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context, arrayList.get(getAdapterPosition()).getTitle(), Toast.LENGTH_SHORT).show();
            }
        });
      }
    }
}

You have to make JSON like below and parse it using Hashmap

    {
  "Header1": [
    {
      "name": "Itemtype1"
    },
    {
      "name": "Itemtype2"
    } 
  ],
"Header2": [
    {
      "name": "Itemtype1"
    },
    {
      "name": "Itemtype2"
    } 
  ],
 "Header3": [
    {
      "name": "Itemtype1"
    },
    {
      "name": "Itemtype2"
    } 
  ]
}

check this example

Related