Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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
like image 451
martin1337 Avatar asked Nov 05 '18 09:11

martin1337


People also ask

Is there an Addheaderview equivalent for RecyclerView?

addItemDecoration(headerDecoration); The decoration is also reusable since there is no need to modify the adapter or the RecyclerView at all.

What is the difference between onCreateViewHolder and onBindViewHolder?

This method internally calls onBindViewHolder to update the ViewHolder contents with the item at the given position and also sets up some private fields to be used by RecyclerView. This method calls onCreateViewHolder to create a new ViewHolder and initializes some private fields to be used by RecyclerView.

Can you use a RecyclerView to display data from a database?

With RecyclerView you can display a table of data, display items in a grid or if you want you can also do a Staggered layout as Pinterest does it with every item being a different size. We will show, what you need for a RecyclerView, with a small app that will show a list of cities.


1 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();
            }
        });
      }
    }
}
like image 54
Ali Ahmed Avatar answered Sep 27 '22 15:09

Ali Ahmed