Multiple row layouts using RecyclerView

Multiple row layouts using RecyclerView


Today I would like to talk about using different row layouts using RecyclerView.

Multiple row layouts using RecyclerView screen

Firstly need to add some dependencies to build.gradle file for using cardView and RecyclerView. For it need to update dependency section in this file:

compile 'com.android.support:cardview-v7:23.2.0'
compile 'com.android.support:recyclerview-v7:23.2.0'

Right now we can start working with RecyclerView. In this short tutorial I’ll create list with Cities and Events. Contain different object in the same list not better idea, but for simple tutorial I hope it’s OK:)

If you want to use different types of row layouts you must to implement next method in adapter:
[java]
@Override
public int getItemViewType(int position) {

}
[/java]

Firstly we can create two different layouts for our recycler view.

item_city
[xml]



[/xml]

item_event
[xml]



[/xml]

Next step is creating a model and dummy data for the application. Firstly need to create the model class which called CityEvent.
[java]
public class CityEvent {
public static final int CITY_TYPE = 0;
public static final int EVENT_TYPE = 1;

private String mName;
private String mDescription;
private int mType;

public CityEvent(String name, String description, int type) {
this.mName = name;
this.mDescription = description;
this.mType = type;
}

public String getName() {
return mName;
}

public void setName(String name) {
this.mName = name;
}

public String getDescription() {
return mDescription;
}

public void setDescription(String description) {
this.mDescription = description;
}

public int getType() {
return mType;
}

public void setType(int type) {
this.mType = type;
}
}
[/java]

After it I created DummyData class.
[java]
public final class DummyData {

public static List getData() {
List list = new ArrayList<>();
list.add(new CityEvent(“London”, null, CityEvent.CITY_TYPE));
list.add(new CityEvent(“Droidcon”, “Droidcon in London”, CityEvent.EVENT_TYPE));
list.add(new CityEvent(“Some event”, “Some event in London”, CityEvent.EVENT_TYPE));
list.add(new CityEvent(“Amsterdam”, null, CityEvent.CITY_TYPE));
list.add(new CityEvent(“Droidcon”, “Droidcon in Amsterdam”, CityEvent.EVENT_TYPE));
list.add(new CityEvent(“Berlin”, null, CityEvent.CITY_TYPE));
list.add(new CityEvent(“Droidcon”, “Droidcon in Berlin”, CityEvent.EVENT_TYPE));
return list;
}
}
[/java]

After it we can implement adapter for recycler view. This class called DifferentRowAdapter.
[java]
public class DifferentRowAdapter extends RecyclerView.Adapter {

private List mList;

public DifferentRowAdapter(List list) {
this.mList = list;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;

switch (viewType) {
case CITY_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_city, parent, false);
return new CityViewHolder(view);
case EVENT_TYPE:
view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_event, parent, false);
return new EventViewHolder(view);
}
return null;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
CityEvent object = mList.get(position);
if (object != null) {
switch (object.getType()) {
case CITY_TYPE:
((CityViewHolder) holder).mTitle.setText(object.getName());
break;
case EVENT_TYPE:
((EventViewHolder) holder).mTitle.setText(object.getName());
((EventViewHolder) holder).mDescription.setText(object.getDescription());
break;
}
}
}

@Override
public int getItemCount() {
if (mList == null)
return 0;
return mList.size();
}

@Override
public int getItemViewType(int position) {
if (mList != null) {
CityEvent object = mList.get(position);
if (object != null) {
return object.getType();
}
}
return 0;
}

public static class CityViewHolder extends RecyclerView.ViewHolder {
private TextView mTitle;

public CityViewHolder(View itemView) {
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.titleTextView);
}
}

public static class EventViewHolder extends RecyclerView.ViewHolder {
private TextView mTitle;
private TextView mDescription;

public EventViewHolder(View itemView) {
super(itemView);
mTitle = (TextView) itemView.findViewById(R.id.titleTextView);
mDescription = (TextView) itemView.findViewById(R.id.descriptionTextView);
}
}
}
[/java]

The last step is updating MainActivity.
[java]
public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

@Override
protected void onStart() {
super.onStart();

DifferentRowAdapter adapter = new DifferentRowAdapter(DummyData.getData());

LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, OrientationHelper.VERTICAL, false);
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(linearLayoutManager);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setAdapter(adapter);
}
}
[/java]

Full source code you can find on Github.

Thank you for you time. I hope it was helpful for you.
Have a nice day.

CategoriesUncategorized

29 thoughts on “Multiple row layouts using RecyclerView

  1. hi,guys this has just been a great tutorial…you have no idea how simple and easy you have made it for me to make sectioned recyclerview now i get the whole concept.

    THANK YOU!!!!!

    1. You can to add this code to required ViewHolder class:
      itemView.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {

      }
      });

      Or you can pass listener object to adapter. And handle listener event from activity, fragment, etc

      1. Thanks for tutorial.
        Could you highlight some info
        regarding item click event.

        eg :
        Today
        item list sorted according to above date
        2 Dec 2017
        item list sorted according to above date
        ……n

        so my problem is I want to pass itemList from selected header i.e. (date) to another fragment . but there is always index bound exception occurs.

        i’ve used hashmap for grouping data according to dates.

        1. I don’t know exactly, because I need more information. Maybe you have problem with last item(s) in your HashMap, because you have header in addition to items

    1. You can to add this code to required ViewHolder class:
      itemView.setOnClickListener(new View.OnClickListener() {
      @Override
      public void onClick(View v) {

      }
      });
      Or you can pass listener object to adapter. And handle listener event from activity, fragment, etc

  2. Lovely post buddy. I am searching for this from long time. I don’t want to use dependancy that make project complicated. Its excellent and clear tutorial.

  3. Can you help me with this?
    Your code worked fine. But i wanna bring Firebase data right now, and put into this arrayList. How can i do that? here is the 3 retrievings (it’s working):

    databaseReference1.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {

    for (DataSnapshot dados : dataSnapshot.getChildren()) {
    Reuniao reuniao = dados.getValueReuniao.class);

    // The values i want to put into the arrayList

    idFinalReuniao = reuniao.getIdDataHoraReuniao();
    clienteReuniao = reuniao.getCliente();
    objetivoReuniao = reuniao.getObjetivo();
    horaReuniao = reuniao.getHora();
    dataReuniao = reuniao.getData();
    localReuniao = reuniao.getLocal();
    extrasReuniao = reuniao.getExtras();

    @Override
    public void onCancelled(DatabaseError databaseError) {
    }
    });

    _____________________________________________________________

    databaseReference2.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {

    for (DataSnapshot dados : dataSnapshot.getChildren()) {
    Processo processo = dados.getValue(Processo.class);

    // The values i want to put into the arrayList
    idFinalProcesso = processo.getIdDataHoraProcesso();
    numeroProcesso = processo.getNumero();
    clienteProcesso = processo.getCliente();
    naturezaProcesso = processo.getNatureza();
    dataProcesso = processo.getData();
    extrasProcesso = processo.getExtras();

    //onCancelled
    ______________________________________________________________

    databaseReference3.addValueEventListener(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {

    for (DataSnapshot dados : dataSnapshot.getChildren()) {
    Audiencia audiencia= dados.getValue(Audiencia.class);

    // The values i want to put into the arrayList
    idFinalAudiencia = audiencia.getIdDataHoraAudiencia();
    processoAudiencia = audiencia.getProcesso();
    clienteAudiencia = audiencia.getCliente();
    naturezaAudiencia = audiencia.getNatureza();
    dataAudiencia = audiencia.getData();
    horaAudiencia = audiencia.getHora();
    extrasAudiencia = audiencia.getExtras();

    //onCancelled

    _______________________________________________________________

    Like you did the CityEvent class, i did one with the data that you see above on the retrieving. Here it is:

    public class DadosFeed {

    public static final int REUNIAO_TYPE = 0;
    public static final int AUDIENCIA_TYPE = 1;
    public static final int PROCESSO_TYPE = 2;
    private int type;

    //private String usuario_id;

    private String idAtividade;
    private String cliente;
    private String objetivo;
    private String hora;
    private String data;
    private String local;
    private String extras;
    private String processo;
    private String natureza;

    public DadosFeed( String idAtividade, String cliente, String objetivo, String hora,
    String data, String local, String extras, String processo, String natureza, int type){
    this.idAtividade = idAtividade;
    this.cliente = cliente;
    this.objetivo = objetivo;
    this.hora = hora;
    this.data = data;
    this.local = local;
    this.extras = extras;
    this.processo = processo;
    this.natureza = natureza;
    this.type = type;

    }

    What can i do to put this data into an arrayList? Please, i really need the answer.
    Thank you!

  4. Thank you so much for this.

    But I have a question. Because of the ability to create dynamic amounts of “headers”, I noticed that they take up positions.

    I’m implementing an “onItemClick” feature, similar to listviews, but I’m finding out that each header in the view takes a position.

    How can I create an argument to remove header positions?

    Thank you again!

      1. here you are adding data statically in the list now i want to add data in list dynamically (i m retrieving data from database).I have list of array which contains row item but i m unable to use it in DummyData .so ,how it can be possible to use array in it

  5. Thank you very much for the tutorial. But i have a question. Although, everything seems to work perfect with debugging only the first two items appear. The only difference in my code is that i call the adapter from a fragment.Is this the possible problem?

  6. tnx.

    I have a problem.I used a layoutAdapter with 3 items in one row.
    I managed to fill them by using some tricks like 3*position 3*position+1 and …
    But in order to implement recycler touch listener , on every 3 items in a row i click
    i get a same position. Please Help.

  7. Thanks for this tutorial. Really helpful.
    But assuming you’re getting the data from Firebase, how will you implement it?

    Let’s say the database looks like this:

    Events: {
    “London”:{
    “Event 1”:{
    “name”: “Droid”,
    “description”: “Droid party in London”},
    “Event 2”:{
    “name”: “Firebase”,
    “description”: “Firebase lecture in London}
    },

    “Amsterdam”:{
    “Event 1”:{
    “name”: “ios”,
    “description”: “ios party with Tim Cook”},
    “Event 2”:{
    “name”: “Firebase”,
    “description”: “Firebase lecture in Amsterdam}
    }
    }

    How do you implement the Event database using Even location as header?

    1. Hello, thank you for your comment.
      In the case of the database for an event, I can propose the model class which can be used for the Room library, or you can create a database using the idea of this class.

      data class Location(
      val city: String
      )

      data class Event(
      val name: String,
      val description: String,
      val eventLocation: Location
      )

      It’s the simplest solution. However, you can use another structure of the database.

  8. Hi, I was wondering is there a way to make an even deeper sectionedView? For example, when I click on DroidCon for the view to expand even more containing subitems for DroidCon? Can you do a tutorial for that please! =)

    1. Hi, thank you for the comment.

      Creating a more in-depth expanded list is possible. However, it can be complicated for the end user, because it requires a long way from the category to the description (Category – Event – Description).

      I’ll re-think this example and create a tutorial for this in future.

Leave a Reply

Your email address will not be published. Required fields are marked *