This example will show you how to add and update RecyclerView items when horizontal scroll it. When the user scrolls from left to right at the beginning of RecyclerView, it will add a new item at the beginning. When the user scrolls from right to left at the end of RecyclerView, it will insert another new item at the ending.
If you can not watch the above video, you can see it on the youtube URL https://youtu.be/zPSxzVdjE6Y
- First, you should add below dependency library in the project build.gradle file dependencies section.
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 as below.
./ ├── app │ ├── build.gradle │ ├── proguard-rules.pro │ └── src │ ├── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ │ └── com │ │ │ └── dev2qa │ │ │ └── example │ │ │ ├── view │ │ │ │ ├── recycler_view │ │ │ │ │ ├── CustomRecyclerViewDataAdapter.java │ │ │ │ │ ├── CustomRecyclerViewHolder.java │ │ │ │ │ ├── CustomRecyclerViewItem.java │ │ │ │ │ └── CustomRecyclerViewScrollActivity.java
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 recycler view object. 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.
- This file is saved in the app/res/layout folder.
- 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; 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.
- This XML file is 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; 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; public class CustomRecyclerViewItem { private String text; public String getText() { return text; } public void setText(String text) { this.text = text; } }
8. Android Manifest Xml File.
- This file is saved in the 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>
i am beginner in this field, please help me out how to change images in this code.
Thanks for this Reference