Android Recyclerview Horizontal Scroll Example

This example will show you how to add and update RecyclerView items when horizontal scroll it. When user scroll from left to right at the beginning of RecyclerView, it will add a new item at beginning. When user scroll from right to left at the end of RecyclerView, it will insert another new item at the ending.

android recyclerview horizontal scroll example

First you should add below dependency library in project build.gradle file.

compile 'com.android.support:cardview-v7:26.+'
compile 'com.android.support:recyclerview-v7:26.+'

1. Example Java File Structure.

There are 4 java files, 1 activity layout xml file and 1 recyclerview item layout xml file.

horizontal scroll android recyclerview java files new

2. Main Activity.

CustomRecyclerViewScrollActivity.java

package com.dev2qa.example.view.recycler_view;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import android.widget.ProgressBar;
import android.widget.Toast;

import com.dev2qa.example.R;

import java.util.ArrayList;
import java.util.List;

public class CustomRecyclerViewScrollActivity extends AppCompatActivity {

    private static final String LOG_TAG = CustomRecyclerViewScrollActivity.class.getSimpleName();

    private RecyclerView recyclerView = null;

    private List<CustomRecyclerViewItem> itemList = null;

    private CustomRecyclerViewDataAdapter customRecyclerViewDataAdapter = null;

    private ProgressBar progressBar = null;

    // This handler is used to update activity UI components/
    private Handler uiHandler = null;

    private int MESSAGE_UPDATE_RECYCLER_VIEW = 1;

    private String MESSAGE_KEY_NEW_ITEM_INDEX = "MESSAGE_KEY_NEW_ITEM_INDEX";

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

        setTitle("dev2qa.com - Android RecyclerView Horizontal Scroll Example.");

        initControls();

        // Create the recyclerview.
        RecyclerView recyclerView = (RecyclerView)findViewById(R.id.custom_refresh_recycler_view);
        // Create the grid layout manager with 2 columns.
        GridLayoutManager layoutManager = new GridLayoutManager(this,1);
        layoutManager.setOrientation(LinearLayoutManager.HORIZONTAL);
        //layoutManager.setOrientation(LinearLayoutManager.VERTICAL);

        // Set layout manager.
        recyclerView.setLayoutManager(layoutManager);

        // Create car recycler view data adapter with car item list.
        customRecyclerViewDataAdapter = new CustomRecyclerViewDataAdapter(itemList);
        // Set data adapter.
        recyclerView.setAdapter(customRecyclerViewDataAdapter);

        // Scroll RecyclerView a little to make later scroll take effect.
        recyclerView.scrollToPosition(1);
    }

    private void initControls()
    {
        if(recyclerView == null)
        {
            recyclerView = (RecyclerView)findViewById(R.id.custom_refresh_recycler_view);

            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {

                @Override
                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                    super.onScrolled(recyclerView, dx, dy);

                    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();

                    int firstCompleteVisibleItemPosition = -1;
                    int lastCompleteVisibleItemPosition = -1;
                    int visibleItemCount = layoutManager.getChildCount();
                    int totalItemCount = layoutManager.getItemCount();

                    if(layoutManager instanceof GridLayoutManager)
                    {
                        GridLayoutManager gridLayoutManager = (GridLayoutManager)layoutManager;
                        firstCompleteVisibleItemPosition = gridLayoutManager.findFirstCompletelyVisibleItemPosition();
                        lastCompleteVisibleItemPosition = gridLayoutManager.findLastCompletelyVisibleItemPosition();
                    }else if(layoutManager instanceof  LinearLayoutManager)
                    {
                        LinearLayoutManager linearLayoutManager = (LinearLayoutManager)layoutManager;
                        firstCompleteVisibleItemPosition = linearLayoutManager.findFirstCompletelyVisibleItemPosition();
                        lastCompleteVisibleItemPosition = linearLayoutManager.findLastCompletelyVisibleItemPosition();
                    }

                    String message = "";

                    // Means scroll at beginning ( top to bottom or left to right).
                    if(firstCompleteVisibleItemPosition == 0)
                    {
                        // dy < 0 means scroll to bottom, dx < 0 means scroll to right at beginning.
                        if(dy < 0 || dx < 0)
                        {
                            // Means scroll to bottom.
                            if(dy < 0)
                            {
                                loadData(true);
                            }

                            // Means scroll to right.
                            if(dx < 0 )
                            {
                                loadData(true);
                            }
                        }
                    }
                    // Means scroll at ending ( bottom to top or right to left )
                    else if(lastCompleteVisibleItemPosition == (totalItemCount - 1))
                    {
                        // dy > 0 means scroll to up, dx > 0 means scroll to left at ending.
                        if(dy > 0 || dx > 0)
                        {
                            // Scroll to top
                            if(dy > 0)
                            {
                                loadData(false);
                            }

                            // Scroll to left
                            if(dx > 0 )
                            {
                                loadData(false);
                            }
                        }
                    }

                    if(message.length() > 0) {
                        Toast.makeText(getApplicationContext(), message, Toast.LENGTH_LONG).show();
                    }
                }
            });
        }

        if(uiHandler == null)
        {
            uiHandler = new Handler()
            {
                @Override
                public void handleMessage(Message msg) {
                    // If the message want to refresh list view.
                    if(msg.what == MESSAGE_UPDATE_RECYCLER_VIEW)
                    {
                        // Refresh list view after add item data.
                        customRecyclerViewDataAdapter.notifyDataSetChanged();
                    }

                    Bundle bundle = msg.getData();
                    int newItemIndex = bundle.getInt(MESSAGE_KEY_NEW_ITEM_INDEX);
                    recyclerView.scrollToPosition(newItemIndex - 1);

                    // Stop showing the progress bar.
                    progressBar.setVisibility(View.GONE);
                }
            };
        }

        if(itemList == null)
        {
            itemList = new ArrayList<CustomRecyclerViewItem>();
            for(int i=0;i<6;i++)
            {
                CustomRecyclerViewItem item = new CustomRecyclerViewItem();
                item.setText("Card " + (i + 1));
                itemList.add(item);
            }
        }

        if(progressBar == null)
        {
            progressBar = (ProgressBar)findViewById(R.id.custom_refresh_recycler_view_progressbar);
        }
    }


    private void loadData(final boolean insertDataAtBeginning)
    {

        // Show progressbar first.
        progressBar.setVisibility(View.VISIBLE);

        Thread workerThread = new Thread()
        {
            @Override
            public void run() {
                try {

                    Thread.sleep(3000);

                    int currItemListSize = itemList.size();

                    int newItemIndex = 0;

                    // Only add one RecyclerView item.
                    for (int i = currItemListSize; i < currItemListSize + 1; i++){

                        CustomRecyclerViewItem newViewItem = new CustomRecyclerViewItem();
                        newViewItem.setText("Card " + (i + 1));

                        if (insertDataAtBeginning) {
                            itemList.add(i - currItemListSize, newViewItem);
                            newItemIndex = 0;
                        }else
                        {
                            itemList.add(newViewItem);
                            newItemIndex = itemList.size() - 1;
                        }

                        Message message = new Message();
                        message.what = MESSAGE_UPDATE_RECYCLER_VIEW;
                        Bundle bundle = new Bundle();
                        bundle.putInt(MESSAGE_KEY_NEW_ITEM_INDEX, newItemIndex);
                        message.setData(bundle);
                        uiHandler.sendMessage(message);
                    }
                }catch(InterruptedException ex)
                {
                    Log.e(LOG_TAG, ex.getMessage(), ex);
                }
            }
        };

        workerThread.start();
    }
}

3. Main Activity Layout Xml File.

Saved in app / res / layout folder.

READ :   Android Count Down Timer Example

activity_custom_refresh_recycler_view.xml

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/custom_refresh_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"/>

    <ProgressBar
        android:id="@+id/custom_refresh_recycler_view_progressbar"
        style="@android:style/Widget.Holo.Light.ProgressBar.Large.Inverse"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:foregroundGravity="center_vertical"
        android:visibility="gone" />

</LinearLayout>

4. RecyclerView Data Adapter Class.

CustomRecyclerViewDataAdapter.java

package com.dev2qa.example.view.recycler_view;

import android.support.v7.widget.RecyclerView.Adapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.dev2qa.example.R;

import java.util.List;

/**
 * Created by Jerry on 3/19/2018.
 */

public class CustomRecyclerViewDataAdapter extends Adapter<CustomRecyclerViewHolder> {

    private List<CustomRecyclerViewItem> viewItemList;

    public CustomRecyclerViewDataAdapter(List<CustomRecyclerViewItem> viewItemList) {
        this.viewItemList = viewItemList;
    }

    @Override
    public CustomRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // Get LayoutInflater object.
        LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
        // Inflate the RecyclerView item layout xml.
        View itemView = layoutInflater.inflate(R.layout.activity_custom_refresh_recycler_view_item, parent, false);

        // Create and return our customRecycler View Holder object.
        CustomRecyclerViewHolder ret = new CustomRecyclerViewHolder(itemView);
        return ret;
    }

    @Override
    public void onBindViewHolder(CustomRecyclerViewHolder holder, int position) {
        if(viewItemList!=null) {
            // Get car item dto in list.
            CustomRecyclerViewItem viewItem = viewItemList.get(position);

            if(viewItem != null) {
                // Set car item title.
                holder.getTextView().setText(viewItem.getText());;
            }
        }
    }

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

5. RecyclerView Item Layout Xml File.

Saved in app / res / layout folder.

activity_custom_refresh_recycler_view_item.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    app:cardCornerRadius="8dp"
    app:cardElevation="10dp">

    <TextView
        android:id="@+id/custom_refresh_recycler_view_text_view"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:gravity="center"
        android:textSize="20dp"/>

</android.support.v7.widget.CardView>

6. RecyclerView View Holder Class.

CustomRecyclerViewHolder.java

package com.dev2qa.example.view.recycler_view;

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

import com.dev2qa.example.R;

/**
 * Created by Jerry on 3/19/2018.
 */

public class CustomRecyclerViewHolder extends RecyclerView.ViewHolder {

    private TextView textView = null;

    public CustomRecyclerViewHolder(View itemView) {
        super(itemView);

        if(itemView != null)
        {
            textView = (TextView)itemView.findViewById(R.id.custom_refresh_recycler_view_text_view);
        }
    }

    public TextView getTextView() {
        return textView;
    }
}

7. RecyclerView View Item DTO Java File.

CustomRecyclerViewItem.java

package com.dev2qa.example.view.recycler_view;

/**
 * Created by Jerry on 3/19/2018.
 */

public class CustomRecyclerViewItem {

    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

8. Android Manifest Xml File.

Saved in app / manifests folder.

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.dev2qa.example">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        
        <activity android:name=".view.recycler_view.CustomRecyclerViewScrollActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
(Visited 8,257 times, 1 visits today)

1 Comment

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.