Open In App

How to Display Data in Tabular Form using Android RecyclerView?

Improve
Improve
Like Article
Like
Save
Share
Report

RecyclerView is a ViewGroup added to the android studio as a successor of the GridView and ListView. It is an improvement on both of them and can be found in the latest v-7 support packages. It has been created to make possible the construction of any lists with XML layouts as an item that can be customized vastly while improving the efficiency of ListViews and GridViews. This improvement is achieved by recycling the views which are out of the visibility of the user. For example, if a user scrolled down to a position where items 4 and 5 are visible; items 1, 2, and 3 would be cleared from the memory to reduce memory consumption. Not just this but Recycler View can also be used for displaying a large number of data in a form of a table. Just like a spreadsheet we can create a highly customizable tabular structure to populate data within it. In this article, we will see how we can build such a tabular structure and populate data from a database. In this case, we are using the Firebase database, but you can use any database. So follow the below steps and let’s get started.

Step by Step Implementation

Step 1: Create a New Project

To create a new project in Android Studio please refer to How to Create/Start a New Project in Android Studio. Note that select Java as the programming language.

Step 2: Creating the Model class

Create a new class named Model which will hold the various data entered by the user. In this case, we are storing string data user name and three other integer data correct, attempted, time. This data represents Quiz contest results. Below is the code to implement the proper Model class. To create a model class we declare private class variables and generate their getters and setter along with the constructor of the class.

Java




public class Record {
 
    // Create private data variables
    private String attempted;
    private String correct;
    private String time;
    private String name;
 
    // generate getters and setters
    public String getName() {
        return name;
    }
 
    public void setName(String name) {
        this.name = name;
    }
 
    public String getAttempted() {
        return attempted;
    }
 
    public void setAttempted(String attempted) {
        this.attempted = attempted;
    }
 
    public String getCorrect() {
        return correct;
    }
 
    public void setCorrect(String correct) {
        this.correct = correct;
    }
 
    public String getTime() {
        return time;
    }
 
    public void setTime(String time) {
        this.time = time;
    }
}


Step 3: Working with the activity_main.xml file

The XML codes are used to build the structure of the activity as well as its styling part. In this XML file, we will create a LinearLayout with horizontal orientation. This will contain four ImageView denoting icons for various data columns of the Record class data model entity. Below that we will create a RecyclerView where the data will populate. Below is the code for the activity_main.xml file.

XML




<RelativeLayout
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/bg_blue">
 
      <!-- Linear layout of horizontal orientation -->
    <LinearLayout
        android:id="@+id/ll1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_below="@+id/railQuiz"
        android:layout_marginTop="20dp"
        android:background="#D6EEEE">
 
          <!-- icon for user name column heading -->
        <ImageView
            android:id="@+id/userName"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:src="@drawable/user_record_icon"
            android:padding="5dp"/>
 
 
          <!-- icon for number of attempted column heading -->
        <ImageView
            android:id="@+id/attempted"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:src="@drawable/attempted_icon"
            android:padding="5dp"/>
 
          <!-- icon for number of correct column heading -->
        <ImageView
            android:id="@+id/correct"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:src="@drawable/correct_icon"
            android:padding="5dp"/>
 
          <!-- icon for time taken column heading -->
        <ImageView
            android:id="@+id/time"
            android:layout_width="match_parent"
            android:layout_height="50dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:src="@drawable/time_icon"
            android:padding="5dp"/>
 
    </LinearLayout>
 
      <!-- Recycler view for populating data in a table format -->
    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/ll1"
        android:background="#D6EEEE" />
 
</RelativeLayout>


Step 4: Creating RecyclerView Item Layout

In this next step, we will create an item layout that will hold our data for every RecyclerView item. In this layout, there will be four views of TextView with the different id attributes. 

XML




<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:paddingTop="15dp"
    android:paddingBottom="15dp"
    android:layout_marginBottom="3dp">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">
 
        <TextView
            android:id="@+id/userName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="Naman Kumar Jha"
            android:textColor="@color/black"
            android:textSize="20dp" />
 
        <TextView
            android:id="@+id/attempted"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:text="40"
            android:textColor="@color/black"
            android:textSize="20dp" />
 
        <TextView
            android:id="@+id/correct"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:text="23"
            android:textColor="@color/black"
            android:textSize="20dp" />
 
        <TextView
            android:id="@+id/time"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:gravity="center"
            android:text="48"
            android:textColor="@color/black"
            android:textSize="20dp" />
 
    </LinearLayout>
 
</androidx.constraintlayout.widget.ConstraintLayout>


Step 5: Working with ViewHolder 

In this, we will create a view holder for our data model class. View holder is used to describe metadata and its location within the recycler view. Here we will use the view holder to place data of the model class variables that are name, attempted, correct, time. Below is the code for ViewHolder.

Java




mport android.view.View;
import android.widget.TextView;
 
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
 
 
public class MyViewHolder extends RecyclerView.ViewHolder {
 
    // data variables to link with
    // the respective id from the view
    TextView name, attempted, correct, time;
 
    public MyViewHolder(@NonNull View itemView) {
        super(itemView);
 
        name = itemView.findViewById(R.id.userName);
        attempted = itemView.findViewById(R.id.attempted);
        correct = itemView.findViewById(R.id.correct);
        time = itemView.findViewById(R.id.time);
 
    }
}


Step 6: Working on Adapter Class

The adapter is the main code responsible for RecyclerView. It holds all the important methods dealing with the implementation of RecylcerView. The basic methods for a successful implementation are:

  • onCreateViewHolder: which deals with the inflation of the card layout as an item for the RecyclerView.
  • onBindViewHolder: which deals with the setting of different data and methods related to clicks on particular items of the RecyclerView.
  • getItemCount: which Returns the length of the RecyclerView.
  • onAttachedToRecyclerView: which attaches the adapter to the RecyclerView.

Java




import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
 
// Extends the Adapter class to RecyclerView.Adapter
// and implement the unimplemented methods
public class RecordAdapter extends RecyclerView.Adapter<MyViewHolder> {
 
    Context context;
    ArrayList<Record> list;
 
    // constructor with Record's data model list and view context
    public RecordAdapter(Context context, ArrayList<Record> list) {
        this.context = context;
        this.list = list;
    }
 
    // Binding data to the
    // into specified position
    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        // inflate the recycler view
        // layout in its view component
        View v = LayoutInflater.from(context).inflate(R.layout.record_info,parent,false);
        return  new MyViewHolder(v);
    }
 
    // holder method to set respective
    // data to their components
    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        Record user = list.get(position);
        holder.name.setText(user.getName());
        holder.attempted.setText(user.getAttempted());
        holder.correct.setText(user.getCorrect());
        holder.time.setText(user.getTime());
    }
 
    // method to return the
    // position of the item
    @Override
    public int getItemCount() {
        return list.size();
    }
 
}


Step 7: Working on RecordActivity Class

In this class, we create instances for the RecyclerView, Adapter Class, ViewHolder. Here we are using the Firebase database to store data store and make request calls to it, you can use any other database. 

  • Create an object of adapter, view holder, recycler view, database reference.
  • Create ArrayList of Object type of Record class.
  • Request data and store it in the array list.
  • Notify the adapter for the changes on the list.

Java




import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.google.android.gms.auth.api.signin.GoogleSignIn;
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
import java.util.ArrayList;
import java.util.Objects;
 
public class RecordActivity extends AppCompatActivity {
 
    private ImageView back, profileImage;
 
    private DatabaseReference databaseReference;
 
    private RecyclerView recyclerView;
 
    private RecordAdapter myAdapter;
 
    // Using ArrayList to Record data
    private ArrayList<Record> list;
 
    private int flag = 0;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_record);
        getRecord();
    }
 
    private void getRecord() {
 
        // Getting reference of recyclerView
        recyclerView = findViewById(R.id.recyclerView);
        recyclerView.setHasFixedSize(true);
       
        // Setting the layout as linear
        // layout for vertical orientation
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
 
        list = new ArrayList<>();
        myAdapter = new RecordAdapter(this,list);
       
        // Setting Adapter to RecyclerView
        recyclerView.setAdapter(myAdapter);
 
        // get firebase instance for the desired key location
        databaseReference = FirebaseDatabase.getInstance().getReference();
        databaseReference.child("User").addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot snapshot) {
                if(flag==0) {
                    for (DataSnapshot ds : snapshot.getChildren()) {
                        for (DataSnapshot dss : ds.getChildren()) {
                            if (Objects.equals(dss.getKey(), "Total")) {
                                // adding record data to the list
                                Record user = dss.getValue(Record.class);
                                list.add(user);
                            }
                        }
                    }
                    // notifying adapter class about the change
                    myAdapter.notifyDataSetChanged();
                    flag=1;
                }
                progressBar.dismiss();
            }
 
            @Override
            public void onCancelled(@NonNull DatabaseError error) {
 
            }
        });
    }
 
    @Override
    public void onBackPressed() {
        startActivity(new Intent(getApplicationContext(), MainActivity.class));
        super.onBackPressed();
    }
}


Output:

Things to remember:

  • The model class should have the required data variables in a specific order.
  • View holder shall inflate the recycler view for it to populate the data.
  • To make an onClick call on a specific row use the onItemCount method.


Last Updated : 28 Mar, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads