Android RecyclerView
Android RecyclerView is the advanced version of ListView for more improvements and features. You can create an attached list with ListView but with RecyclerView, you can do more with recyclerview:
1. Reuses cells while scrolling
2. Animate to list items
3. Change the item container ( linear layout or grid layout using Layout Manager)
4. Divider between two items
5. Multiple views in the same listing
In this article, we are going to learn how to use RecyclerView. The RecyclerView that we are going to design contains our solar system planets information with RecyclerView. Let’s start.
After creating a new project, open build.gradle file from app level and add RecyclerView dependency: com.android.support:recyclerview-v7:27.0.2 and sync project.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"><include layout="@layout/app_bar" /><android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"></android.support.v7.widget.RecyclerView></LinearLayout>
app_bar.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:gravity="center_vertical"
android:title=""
app:layout_collapseMode="pin"
app:layout_scrollFlags="scroll|enterAlways"
app:theme="@style/MyToolbarTheme"></android.support.v7.widget.Toolbar>
Create a class Planet.java with getter/setter, it’s our POJO. For each row in RecyclerView.
package com.example.demoproject;
public class Planet {private String planetName;
private int distanceFromSun;
private int gravity;
private int diameter;public Planet(String planetName, int distanceFromSun, int gravity, int diameter) {
this.planetName = planetName;
this.distanceFromSun = distanceFromSun;
this.gravity = gravity;
this.diameter = diameter;
}public String getPlanetName() {
return planetName;
}public void setPlanetName(String planetName) {
this.planetName = planetName;
}public int getDistanceFromSun() {
return distanceFromSun;
}public void setDistanceFromSun(int distanceFromSun) {
this.distanceFromSun = distanceFromSun;
}public int getGravity() {
return gravity;
}public void setGravity(int gravity) {
this.gravity = gravity;
}public int getDiameter() {
return diameter;
}public void setDiameter(int diameter) {
this.diameter = diameter;
}
}
Create a layout for RecyclerView item row item_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="4dp">
<TextView
android:id="@+id/txtName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="1dp"
android:textSize="18sp" /><TextView
android:id="@+id/txtDistance"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="1dp" /><TextView
android:id="@+id/txtGravity"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="1dp" /><TextView
android:id="@+id/txtDiameter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="1dp" />
</LinearLayout>
Now create adapter class PlanetAdapter.java step-wise for recyclerview base. Follow these steps for easily create adapter without any complex structure. Below steps are for RecyclerView adapter class.
1. Create class PlanetAdapter.java
public class PlanetAdapter {
}
2. Create ViewHolder for RecyclerView
public class PlanetHolder extends RecyclerView.ViewHolder {private TextView txtName, txtDistance, txtGravity, txtDiameter;public PlanetHolder(View itemView) {
super(itemView);
txtName = itemView.findViewById(R.id.txtName);
txtDistance = itemView.findViewById(R.id.txtDistance);
txtGravity = itemView.findViewById(R.id.txtGravity);
txtDiameter = itemView.findViewById(R.id.txtDiameter);
}
}
3. Extends adapter class to RecyclerView.Adapter<PlanetHolder> and implements override methods onCreateViewHolder, onBindViewHolder and getItemCount.
4. Define context and ArrayList and create a constructor.
private Context context;private ArrayList<Planet> planets;
public PlanetAdapter(Context context, ArrayList<Planet> planets) {this.context = context;
this.planets = planets;
}
5. Change getItemCount() method
@Override
public int getItemCount() {
return planets.size();
}
6. Inflate item layout in onCreateViewHolder() method and inflate item_row for recyclerview
@Override
public PlanetHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item_row, parent, false);
return new PlanetHolder(view);
}
7. Create a method in PlanetHolder class for set values for each planet to item row.
public void setDetails(Planet planet) {
txtName.setText(planet.getPlanetName());
txtDistance.setText(String.format(Locale.US, "Distance from Sun : %d Million KM", planet.getDistanceFromSun()));
txtGravity.setText(String.format(Locale.US, "Surface Gravity : %d N/kg", planet.getGravity()));
txtDiameter.setText(String.format(Locale.US, "Diameter : %d KM", planet.getDiameter()));
}
8. Call this method from onBindViewHolder() method to bind item of recyclerview
@Override
public void onBindViewHolder(PlanetHolder holder, int position) {
Planet planet = planets.get(position);
holder.setDetails(planet);
}
Now change your activity code as below:
- set recyclerview layout manager
- set adapter for recyclerview
- fill data for recyclerview items
- set data to adapter and notify data
package com.example.demoproject;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
public class DemoActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private PlanetAdapter adapter;
private ArrayList<Planet> planetArrayList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_demo);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
planetArrayList = new ArrayList<>();
adapter = new PlanetAdapter(this, planetArrayList);
recyclerView.setAdapter(adapter);
createListData();
}
private void createListData() {
Planet planet = new Planet("Earth", 150, 10, 12750);
planetArrayList.add(planet);
planet = new Planet("Jupiter", 778, 26, 143000);
planetArrayList.add(planet);
planet = new Planet("Mars", 228, 4, 6800);
planetArrayList.add(planet);
planet = new Planet("Pluto", 5900, 1, 2320);
planetArrayList.add(planet);
planet = new Planet("Venus", 108, 9, 12750);
planetArrayList.add(planet);
planet = new Planet("Saturn", 1429, 11, 120000);
planetArrayList.add(planet);
planet = new Planet("Mercury", 58, 4, 4900);
planetArrayList.add(planet);
planet = new Planet("Neptune", 4500, 12, 50500);
planetArrayList.add(planet);
planet = new Planet("Uranus", 2870, 9, 52400);
planetArrayList.add(planet);
adapter.notifyDataSetChanged();
}
}
What is LayoutManager?
A LayoutManager is responsible for measuring and positioning item views within a recyclerview as well as determining the policy for when to recycle item views that are no longer visible to the user. By changing the layout manager, recyclerview can be used to implement a standard vertically scrolling list, a uniform grid, staggered grids, horizontally scrolling collections and more. Several stock layout managers are provided for general use.
Now run the app and see the output as below:
If you want to put a divider between two items in RecyclerView, use ItemDecoration code as below before setAdapter() method:
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
recyclerView.setAdapter(adapter);
You can see divider slightly highlighted. You can customize this divider color. As below you can see, I changed RecyclerView background color to HEX #3E3963(blue) and divider color to HEX #FAA701(semi_yellow) and text color for item_row elements to HEX #FFFFFF(white)
Create custom divider item decoration class for divider in recyclerview LineDividerItemDecoration.java
package com.example.demoproject;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class LineDividerItemDecoration extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public LineDividerItemDecoration(Context context, int dividerDrawable) {
mDivider = ContextCompat.getDrawable(context, dividerDrawable);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
Create custom drawable for divider line_divider.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<size
android:width="1dp"
android:height="1dp" />
<solid android:color="@color/semi_yellow" />
</shape>
Add this line before setAdapter() for divider in RecyclerView:
recyclerView.addItemDecoration(new LineDividerItemDecoration(this, R.drawable.line_divider));
Output:
Now put click listener on itemView in PlanetHolder class, setDetails() method.
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// handle click event
}
});public void setDetails(Planet planet) {
txtName.setText(planet.getPlanetName());
txtDistance.setText(String.format(Locale.US, "Distance from Sun : %d Million KM", planet.getDistanceFromSun()));
txtGravity.setText(String.format(Locale.US, "Surface Gravity : %d N/kg", planet.getGravity()));
txtDiameter.setText(String.format(Locale.US, "Diameter : %d KM", planet.getDiameter()));
}
You can change RecyclerView layout manager from linear to grid as shown below with 2 column-span:
recyclerView.setLayoutManager(new GridLayoutManager(this, 2));
That’s it. Create your own design using color combinations and margins in RecyclerView. In the next article, we will be going to teach you Android CardView with RecyclerView.
Find source here.