RecyclerView is the most powerful, advanced and flexible version of ListView. In RecyclerView is used several different components work together to display data. Using the standard layout managers  (such as LinearLayoutManager or GridLayoutManager ), you can create the list and grid both very easily.

RecyclerView model is a lot of optimized and powerful. As the suggest RecyclerView is used the reusable cell when scrolling up and down. Suppose the view is displaying list positions 0 to 9 the RecyclerView has bind those view holders when user scroll down RecyclerView reuse the cell and bind with holder. One more improvement in RecyclerView is that allows us to set layout managers at runtime so we can manage scrolling such as vertical or horizontal and manage view in such as list, grid, and Staggered layout.

In this tutorial, We are going to explain best practices to implement RecyclerView in Android. We will create a custom layout with CardView and render it on RecyclerView. We discuss in detail about some relevant classes such as LayoutManager, ViewHolder, Adapter, ItemDecoration etc.

Prerequisite

You need to have knowledge of following classes that used in RecyclerView implementation
  • Adapter – Provides the data model and responsible for rendering the views for the individual cell
  • ViewHolder – Contains instances for all views that are filled by the data of the entry
  • LayoutManager – Allows us to set the LayoutManagers at runtime. eg. LinearLayoutManager, StaggeredLayoutManager, GridLayoutManager
RecyclerView Sample App
Add the support library

Open the build.gradle file in app module and add followings dependency

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.2'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.1.0-alpha4'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4'
    implementation 'androidx.cardview:cardview:1.0.0-beta01'
    implementation 'androidx.recyclerview:recyclerview:1.0.0-beta01'
    implementation 'com.google.android.material:material:1.0.0-beta01'
    implementation 'com.google.code.gson:gson:2.8.5'
    // ButterKnife for view binding
    implementation 'com.jakewharton:butterknife:10.0.0'
    annotationProcessor 'com.jakewharton:butterknife-compiler:10.0.0'
    // Glide for image loading
    implementation 'com.github.bumptech.glide:glide:4.8.0'
    annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'
}
Set Java version 1.8 for using lambda expression
  compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
Open the color.xml in from res=>value folder and add color values
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#4CAF50</color>
    <color name="colorPrimaryDark">#388E3C</color>
    <color name="colorPrimaryLight">#C8E6C9</color>
    <color name="colorAccent">#FF9800</color>
    <color name="colorPrimaryText">#212121</color>
    <color name="colorSecondaryText">#757575</color>
    <color name="colorIcons">#FFFFFF</color>
    <color name="colorDivider">#BDBDBD</color>
    <color name="black_effective">#2a2a2a</color>
</resources>
Go to string.xml from res => values=> string.xml and add some string values

Open string.xml add string values and demo content arrays for showing in list.

<resources>
    <string name="app_name">RecyclerView</string>
    <string name="title_placeholder">Title</string>
    <string name="news_placeholder">News</string>
    <string name="sports_info_placeholder">Here is some news</string>
    <string name="empty_screen">We do not have anything\nhere right now. Please Retry</string>
    <string name="btn_retry">Retry</string>

    <string-array name="sports_images">
        <item>https://androidwave.com/media/images/img_baseball.jpg</item>
        <item>https://androidwave.com/media/images/img_badminton.jpg</item>
        <item>https://androidwave.com/media/images/img_basketball.jpg</item>
        <item>https://androidwave.com/media/images/img_bowling.jpg</item>
        <item>https://androidwave.com/media/images/img_cycling.jpg</item>
        <item>https://androidwave.com/media/images/img_golf.jpg</item>
        <item>https://androidwave.com/media/images/img_running.jpg</item>
        <item>https://androidwave.com/media/images/img_soccer.jpg</item>
        <item>https://androidwave.com/media/images/img_swimming.jpg</item>
        <item>https://androidwave.com/media/images/img_tabletennis.jpg</item>
        <item>https://androidwave.com/media/images/img_tennis.jpg</item>
    </string-array>
    <string-array name="sports_titles">
        <item>Baseball</item>
        <item>Badminton</item>
        <item>Basketball</item>
        <item>Bowling</item>
        <item>Cycling</item>
        <item>Golf</item>
        <item>Running</item>
        <item>Soccer</item>
        <item>Swimming</item>
        <item>Table Tennis</item>
        <item>Tennis</item>
    </string-array>

    <string-array name="sports_info">
        <item>Nike Enters 10-Year Partnership With Major League Baseball! </item>
        <item>Indonesia Masters – Saina Nehwal sails into semifinals PV Sindhu, Kidambi Srikanth lose in quarters!</item>
        <item>College Basketball 2018–19 Player of the Year Power Rankings Everyone is chasing Dukes Zion Williamson!</item>
        <item>Local bowler lands 132 perfect games, shares his secret for success!</item>
        <item>Sierra solos to win at womens Cadel Evans Great Ocean Road Race!</item>
        <item>Tiger Woods Friday live blog: Woods overcomes mid-round hiccup to make the cut at Torrey Pines!</item>
        <item>The 5km fun run was organised by Ironman England as part of its annual three-day triathlon festival in Bolton, Manchester in a bid to attract more female runners to the event!</item>
        <item>Soccer insider notes: Liverpool not the only Premier League club eyeing Weston McKennie!</item>
        <item>Chloe Grimme, a USA Swimming Scholastic All American from Land O Lakes, Florida, announced on social media that she has verbally committed to the University of Florida for 2020–21!</item>
        <item>Table Tennis Federation Revokes Soumyajit Ghoshs Suspension, 9 Months After Rape Allegations!</item>
        <item>2019 Australian Open odds, predictions for mens finals!</item>
    </string-array>
</resources>

Create a class with name BaseViewHolder

Go to src and create a new Java class with BaseViewHolder which extends RecyclerView.ViewHolder , We will use BaseViewHolder class instance of RecyclerView holder class, It improves your code quality and eliminate boilerplate code.

package com.androidwave.recyclerview;

import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * Created on : Jan 26, 2019
 * Author     : AndroidWave
 * Email    : info@androidwave.com
 */
public abstract class BaseViewHolder extends RecyclerView.ViewHolder {

    private int mCurrentPosition;

    public BaseViewHolder(View itemView) {
        super(itemView);
    }

    protected abstract void clear();

    public void onBind(int position) {
        mCurrentPosition = position;
        clear();
    }

    public int getCurrentPosition() {
        return mCurrentPosition;
    }
}

Write a Adapter class

Let’s start writing a adapter class with hold the list item and render on RecyclerView in Android.

Create a Model Class with named Sport.java

Create a new POJO class, and define some entity such as title, subtitle, and news discerption with getter setter.

package com.androidwave.recyclerview;
import com.google.gson.annotations.SerializedName;

public class Sport {

    @SerializedName("imageUrl")
    private String mImageUrl;
    @SerializedName("info")
    private String mInfo;
    @SerializedName("subTitle")
    private String mSubTitle;
    @SerializedName("title")
    private String mTitle;

    public Sport(String mImageUrl, String mInfo, String mSubTitle, String mTitle) {
        this.mImageUrl = mImageUrl;
        this.mInfo = mInfo;
        this.mSubTitle = mSubTitle;
        this.mTitle = mTitle;
    }

    public String getImageUrl() {
        return mImageUrl;
    }

    public void setImageUrl(String imageUrl) {
        mImageUrl = imageUrl;
    }

    public String getInfo() {
        return mInfo;
    }

    public void setInfo(String info) {
        mInfo = info;
    }

    public String getSubTitle() {
        return mSubTitle;
    }

    public void setSubTitle(String subTitle) {
        mSubTitle = subTitle;
    }

    public String getTitle() {
        return mTitle;
    }

    public void setTitle(String title) {
        mTitle = title;
    }

}
Create a xml layout with list_item.xml 

Just go to res directory and create a xml layout for displaying a single row of RecyclerView. Which contain some ImageView, TextView along with CardView.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorIcons"
    android:layout_margin="@dimen/_4dp">

    <androidx.cardview.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:elevation="3dp"

        android:padding="@dimen/card_view_margin"
        card_view:cardCornerRadius="@dimen/card_radius">

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ImageView
                android:id="@+id/thumbnail"
                android:layout_width="match_parent"
                android:layout_height="130dp"
                android:background="?attr/selectableItemBackgroundBorderless"
                android:scaleType="fitXY" />

            <TextView
                android:id="@+id/title"
                style="@style/TextAppearance.AppCompat.Headline"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignBottom="@+id/thumbnail"
                android:layout_alignParentStart="true"
                android:layout_marginLeft="@dimen/_8dp"
                android:layout_marginBottom="8dp"
                android:padding="@dimen/_8dp"
                android:text="@string/title_placeholder"
                android:textColor="@color/colorIcons" />

            <TextView
                android:id="@+id/newsTitle"
                style="@style/TextAppearance.AppCompat.Subhead"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/thumbnail"
                android:layout_alignParentStart="true"
                android:layout_marginLeft="@dimen/_8dp"
                android:textStyle="bold"
                android:padding="@dimen/_8dp"
                android:text="@string/news_placeholder" />

            <TextView
                android:id="@+id/newsInfo"
                style="@style/TextAppearance.AppCompat.Subhead"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@+id/newsTitle"
                android:layout_alignParentStart="true"
                android:layout_marginLeft="@dimen/_8dp"
                android:layout_marginBottom="@dimen/_8dp"
                android:padding="@dimen/_8dp"
                android:text="@string/sports_info_placeholder"
                />

        </RelativeLayout>

    </androidx.cardview.widget.CardView>

</LinearLayout>

Create an XML layout which renders at the time when no item added in the list. so create XML class with named is item_empty_view.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">

    <TextView
        android:id="@+id/tv_message"
        style="@style/TextAppearance.AppCompat.Headline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginBottom="8dp"
        android:gravity="center"
        android:text="@string/empty_screen"
        android:textColor="@color/colorSecondaryText"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/buttonRetry"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="8dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="8dp"
        android:text="@string/btn_retry"
        android:background="@color/colorAccent"
        android:textColor="@color/colorIcons"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tv_message" />


</androidx.constraintlayout.widget.ConstraintLayout>
Create a new java class with named is SportAdapter.java

In Java source folder create a SportAdapter.java file which extend RecyclerView.Adapter<BaseViewHolder> , In Adapter class onCreateViewHolder() is responsible to inflate list_tem.xml and item_empty_view.xml of each row and onBindViewHolder()  is bind the data of each row

package com.androidwave.recyclerview;

import android.content.Intent;
import android.net.Uri;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;

/**
 * Created on : Jan 26, 2019
 * Author     : AndroidWave
 * Email    : info@androidwave.com
 */
public class SportAdapter extends RecyclerView.Adapter<BaseViewHolder> {
    private static final String TAG = "SportAdapter";
    public static final int VIEW_TYPE_EMPTY = 0;
    public static final int VIEW_TYPE_NORMAL = 1;

    private Callback mCallback;
    private List<Sport> mSportList;

    public SportAdapter(List<Sport> sportList) {
        mSportList = sportList;
    }

    public void setCallback(Callback callback) {
        mCallback = callback;
    }

    @Override
    public void onBindViewHolder(BaseViewHolder holder, int position) {
        holder.onBind(position);
    }

    @Override
    public BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        switch (viewType) {
            case VIEW_TYPE_NORMAL:
                return new ViewHolder(
                        LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item, parent, false));
            case VIEW_TYPE_EMPTY:
            default:
                return new EmptyViewHolder(
                        LayoutInflater.from(parent.getContext()).inflate(R.layout.item_empty_view, parent, false));
        }
    }

    @Override
    public int getItemViewType(int position) {
        if (mSportList != null &amp;&amp; mSportList.size() > 0) {
            return VIEW_TYPE_NORMAL;
        } else {
            return VIEW_TYPE_EMPTY;
        }
    }

    @Override
    public int getItemCount() {
        if (mSportList != null &amp;&amp; mSportList.size() > 0) {
            return mSportList.size();
        } else {
            return 1;
        }
    }

    public void addItems(List<Sport> sportList) {
        mSportList.addAll(sportList);
        notifyDataSetChanged();
    }

    public interface Callback {
        void onEmptyViewRetryClick();
    }

    public class ViewHolder extends BaseViewHolder {

        @BindView(R.id.thumbnail)
        ImageView coverImageView;

        @BindView(R.id.title)
        TextView titleTextView;

        @BindView(R.id.newsTitle)
        TextView newsTextView;

        @BindView(R.id.newsInfo)
        TextView infoTextView;


        public ViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
        }

        protected void clear() {
            coverImageView.setImageDrawable(null);
            titleTextView.setText("");
            newsTextView.setText("");
            infoTextView.setText("");
        }

        public void onBind(int position) {
            super.onBind(position);

            final Sport mSport = mSportList.get(position);

            if (mSport.getImageUrl() != null) {
                Glide.with(itemView.getContext())
                        .load(mSport.getImageUrl())
                        .into(coverImageView);
            }

            if (mSport.getTitle() != null) {
                titleTextView.setText(mSport.getTitle());
            }

            if (mSport.getSubTitle() != null) {
                newsTextView.setText(mSport.getSubTitle());
            }

            if (mSport.getInfo() != null) {
                infoTextView.setText(mSport.getInfo());
            }

            itemView.setOnClickListener(v -> {
                if (mSport.getImageUrl() != null) {
                    try {
                        Intent intent = new Intent();
                        intent.setAction(Intent.ACTION_VIEW);
                        intent.addCategory(Intent.CATEGORY_BROWSABLE);
                        intent.setData(Uri.parse(mSport.getImageUrl()));
                        itemView.getContext().startActivity(intent);
                    } catch (Exception e) {
                        Log.e(TAG, "onClick: Image url is not correct");
                    }
                }
            });
        }
    }

    public class EmptyViewHolder extends BaseViewHolder {

        @BindView(R.id.tv_message)
        TextView messageTextView;
        @BindView(R.id.buttonRetry)
        TextView buttonRetry;

        EmptyViewHolder(View itemView) {
            super(itemView);
            ButterKnife.bind(this, itemView);
            buttonRetry.setOnClickListener(v -> mCallback.onEmptyViewRetryClick());
        }

        @Override
        protected void clear() {

        }

    }
}

In Adapter class you are seeing a callback interface which responsible to retry to call API or methods in case network failure and server failure . So call back method will call on click of Retr button

  buttonRetry.setOnClickListener(v -> mCallback.onEmptyViewRetryClick());
Add RecyclerView widget in activity_main.xml

You you choose BasicActivity template while creating a project MainActivity and layout file will automatically created . open activity_main.xml and add RecyclerView widget

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
    android:background="#f2f2f2"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/mRecyclerView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginBottom="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginStart="8dp"
        android:layout_marginTop="8dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        />

</androidx.constraintlayout.widget.ConstraintLayout>
Open the MainActivity and add below code

Basically following things we have to do in this class

  • Bind view by id using ButterKnife.
  • Setup LinearLayoutManager and DefaultItemAnimator on RecyclerView.
  • Prepare demo content (In your you can fetch date from the remote server using retrofit).
  • Set the Adapter on RecyclerView
  • Implement Callback methods and call Retry method in case of no item in list
package com.androidwave.recyclerview;

import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;

import com.androidwave.recyclerview.utils.CommonUtils;
import com.androidwave.recyclerview.utils.DividerItemDecoration;

import java.util.ArrayList;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import butterknife.BindView;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity implements SportAdapter.Callback {

    @BindView(R.id.mRecyclerView)
    RecyclerView mRecyclerView;
    SportAdapter mSportAdapter;

    LinearLayoutManager mLayoutManager;

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

    private void setUp() {
        mLayoutManager = new LinearLayoutManager(this);
        mLayoutManager.setOrientation(RecyclerView.VERTICAL);
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());
        Drawable dividerDrawable = ContextCompat.getDrawable(this, R.drawable.divider_drawable);
        mRecyclerView.addItemDecoration(new DividerItemDecoration(dividerDrawable));
        mSportAdapter = new SportAdapter(new ArrayList<>());

        prepareDemoContent();
    }

    private void prepareDemoContent() {
        CommonUtils.showLoading(MainActivity.this);
        new Handler().postDelayed(() -> {
            //prepare data and show loading
            CommonUtils.hideLoading();
            ArrayList<Sport> mSports = new ArrayList<>();
            String[] sportsList = getResources().getStringArray(R.array.sports_titles);
            String[] sportsInfo = getResources().getStringArray(R.array.sports_info);
            String[] sportsImage = getResources().getStringArray(R.array.sports_images);
            for (int i = 0; i < sportsList.length; i++) {
                mSports.add(new Sport(sportsImage[i], sportsInfo[i], "News", sportsList[i]));
            }
            mSportAdapter.addItems(mSports);
            mRecyclerView.setAdapter(mSportAdapter);
        }, 2000);


    }

    @Override
    public void onEmptyViewRetryClick() {
        prepareDemoContent();
    }
}

Add Divider DividerItemDecoration

You are seeing I have added divider between to cell by using DividerItemDecoration. You can manage color and space easily by using below code

Create java class with named DividerItemDecoration which extends RecyclerView.ItemDecoration

package com.androidwave.recyclerview.utils;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;

import android.view.View;

import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

/**
 * Created on : Jan 27, 2019
 * Author     : AndroidWave
 * Email    : info@androidwave.com
 */




public class DividerItemDecoration extends RecyclerView.ItemDecoration {

    private Drawable mDivider;
    private int mOrientation;

    /**
     * Sole constructor. Takes in a {@link Drawable} to be used as the interior
     * divider.
     *
     * @param divider A divider {@code Drawable} to be drawn on the RecyclerView
     */
    public DividerItemDecoration(Drawable divider) {
        mDivider = divider;
    }

    /**
     * Draws horizontal or vertical dividers onto the parent RecyclerView.
     *
     * @param canvas The {@link Canvas} onto which dividers will be drawn
     * @param parent The RecyclerView onto which dividers are being added
     * @param state  The current RecyclerView.State of the RecyclerView
     */
    @Override
    public void onDraw(Canvas canvas, RecyclerView parent, RecyclerView.State state) {
        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
            drawHorizontalDividers(canvas, parent);
        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
            drawVerticalDividers(canvas, parent);
        }
    }

    /**
     * Determines the size and location of offsets between items in the parent
     * RecyclerView.
     *
     * @param outRect The {@link Rect} of offsets to be added around the child
     *                view
     * @param view    The child view to be decorated with an offset
     * @param parent  The RecyclerView onto which dividers are being added
     * @param state   The current RecyclerView.State of the RecyclerView
     */
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);

        if (parent.getChildAdapterPosition(view) == 0) {
            return;
        }

        mOrientation = ((LinearLayoutManager) parent.getLayoutManager()).getOrientation();
        if (mOrientation == LinearLayoutManager.HORIZONTAL) {
            outRect.left = mDivider.getIntrinsicWidth();
        } else if (mOrientation == LinearLayoutManager.VERTICAL) {
            outRect.top = mDivider.getIntrinsicHeight();
        }
    }

    /**
     * Adds dividers to a RecyclerView with a LinearLayoutManager or its
     * subclass oriented horizontally.
     *
     * @param canvas The {@link Canvas} onto which horizontal dividers will be
     *               drawn
     * @param parent The RecyclerView onto which horizontal dividers are being
     *               added
     */
    private void drawHorizontalDividers(Canvas canvas, RecyclerView parent) {
        int parentTop = parent.getPaddingTop();
        int parentBottom = parent.getHeight() - parent.getPaddingBottom();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount - 1; i++) {
            View child = parent.getChildAt(i);

            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            int parentLeft = child.getRight() + params.rightMargin;
            int parentRight = parentLeft + mDivider.getIntrinsicWidth();

            mDivider.setBounds(parentLeft, parentTop, parentRight, parentBottom);
            mDivider.draw(canvas);
        }
    }

    /**
     * Adds dividers to a RecyclerView with a LinearLayoutManager or its
     * subclass oriented vertically.
     *
     * @param canvas The {@link Canvas} onto which vertical dividers will be
     *               drawn
     * @param parent The RecyclerView onto which vertical dividers are being
     *               added
     */
    private void drawVerticalDividers(Canvas canvas, RecyclerView parent) {
        int parentLeft = parent.getPaddingLeft();
        int parentRight = parent.getWidth() - parent.getPaddingRight();

        int childCount = parent.getChildCount();
        for (int i = 0; i < childCount - 1; i++) {
            View child = parent.getChildAt(i);

            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();

            int parentTop = child.getBottom() + params.bottomMargin;
            int parentBottom = parentTop + mDivider.getIntrinsicHeight();

            mDivider.setBounds(parentLeft, parentTop, parentRight, parentBottom);
            mDivider.draw(canvas);
        }
    }
}

Create a drawable class and manage space and divider color here

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <size android:height="@dimen/_4dp" />
    <solid android:color="#EEEEEE" />
</shape>

Finally set on RecyclerView

        Drawable dividerDrawable = ContextCompat.getDrawable(this, R.drawable.divider_drawable);
        mRecyclerView.addItemDecoration(new DividerItemDecoration(dividerDrawable));

After following all above just RUN the project and use app, If you have any queries, feel free to ask them in the comment section below. Happy Coding 🙂

Write A Comment