Android RecyclerView Swipe Refresh Tutorial
In previous tutorial, I have implement a simple recyclerview tutorial to let you understand how its work. The recyclerview only display the static content is not a good practice. We should implement the refresh feature swipe up or down in the recyclerview to refresh the new content from the database or only visible 10 item per load. The swipe down refresh is very useful when come to you dont want to display all item at a time because it will cause the android app lag or some serious problem occur in the user device. So that you want to load and refresh only 10 items per refresh. This tutorial, I will provide the android recyclerview swipe refresh feature in this android project. So you will get use on it.
Creating a new Project
1. Open Android Studio IDE in your computer.
2. Create a new project and Edit the Application name to “SwipeRefreshRecyclerViewExample”.
(Optional) You can edit the company domain or select the suitable location for current project tutorial. Then click next button to proceed.
3. Select Minimum SDK (API 15:Android 4.0.3 (IceCreamSandwich). I choose the API 15 because many android devices currently are support more than API 15. Click Next button.
4. Choose “Empty Project” and Click Next button
5. Lastly, press finish button.
Add the new dependency
Include the recyclerview library in your androidmanifest file so you can use the recyclerview in your project later. After that click synchronise.
compile 'com.android.support:recyclerview-v7:25.0.0'
Create a item view layout
Right click the res>layout folder and create a new xml layout “item_view” for the each item view.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/tvItem" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:textSize="26sp" /> </LinearLayout>
Create a progress view layout
Same as previous, create a layout but name it to “item_progress” after that follow the source code in the bottom.
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"> <ProgressBar android:id="@+id/pBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:indeterminate="true"/> </LinearLayout>
Create a Modal class
Besides, add a new modal class “Item” and follow the sample source code below, I will add one string name item.
public class Item { private String item; public String getItem() { return item; } public void setItem(String item) { this.item = item; } public Item(String item) { this.item=item; } }
Create a new Adapter for Item
Create a new Adapter class “ItemAdapter”, if the item position is null then it will be show the progress bar.
public class ItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final int VIEW_ITEM = 1; private final int VIEW_PROG = 0; private ArrayList<Item> itemList; private OnLoadMoreListener onLoadMoreListener; private LinearLayoutManager mLinearLayoutManager; private boolean isMoreLoading = false; private int visibleThreshold = 1; int firstVisibleItem, visibleItemCount, totalItemCount; public interface OnLoadMoreListener{ void onLoadMore(); } public ItemAdapter(OnLoadMoreListener onLoadMoreListener) { this.onLoadMoreListener=onLoadMoreListener; itemList =new ArrayList<>(); } public void setLinearLayoutManager(LinearLayoutManager linearLayoutManager){ this.mLinearLayoutManager=linearLayoutManager; } public void setRecyclerView(RecyclerView mView){ mView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); visibleItemCount = recyclerView.getChildCount(); totalItemCount = mLinearLayoutManager.getItemCount(); firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition(); if (!isMoreLoading && (totalItemCount - visibleItemCount)<= (firstVisibleItem + visibleThreshold)) { if (onLoadMoreListener != null) { onLoadMoreListener.onLoadMore(); } isMoreLoading = true; } } }); } @Override public int getItemViewType(int position) { return itemList.get(position) != null ? VIEW_ITEM : VIEW_PROG; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,int viewType) { if (viewType == VIEW_ITEM) { return new ItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false)); } else { return new ProgressViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_progress, parent, false)); } } public void addAll(List<Item> lst){ itemList.clear(); itemList.addAll(lst); notifyDataSetChanged(); } public void addItemMore(List<Item> lst){ itemList.addAll(lst); notifyItemRangeChanged(0,itemList.size()); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof ItemViewHolder) { Item singleItem = (Item) itemList.get(position); ((ItemViewHolder) holder).tvItem.setText(singleItem.getItem()); } } public void setMoreLoading(boolean isMoreLoading) { this.isMoreLoading=isMoreLoading; } @Override public int getItemCount() { return itemList.size(); } public void setProgressMore(final boolean isProgress) { if (isProgress) { new Handler().post(new Runnable() { @Override public void run() { itemList.add(null); notifyItemInserted(itemList.size() - 1); } }); } else { itemList.remove(itemList.size() - 1); notifyItemRemoved(itemList.size()); } } static class ItemViewHolder extends RecyclerView.ViewHolder { public TextView tvItem; public ItemViewHolder(View v) { super(v); tvItem = (TextView) v.findViewById(R.id.tvItem); } } static class ProgressViewHolder extends RecyclerView.ViewHolder { public ProgressBar pBar; public ProgressViewHolder(View v) { super(v); pBar = (ProgressBar) v.findViewById(R.id.pBar); } } }
Edit activity_main.xml layout
Go to activity_main.xml file and add the swiperefreshlayout such as the source code below.
<?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"> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefresh" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/rvList" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"/> </android.support.v4.widget.SwipeRefreshLayout> </LinearLayout>
Edit MainActivity.java class
Modify your mainactivity class and this class will handler the swipe feature in the recyclerview.
public class MainActivity extends AppCompatActivity implements ItemAdapter.OnLoadMoreListener ,SwipeRefreshLayout.OnRefreshListener{ private ItemAdapter mAdapter; private ArrayList<Item> itemList; private SwipeRefreshLayout swipeRefresh; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); itemList = new ArrayList<Item>(); swipeRefresh=(SwipeRefreshLayout)findViewById(R.id.swipeRefresh); RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.rvList); LinearLayoutManager mLayoutManager = new LinearLayoutManager(this); mRecyclerView.setLayoutManager(mLayoutManager); mAdapter = new ItemAdapter(this); mAdapter.setLinearLayoutManager(mLayoutManager); mAdapter.setRecyclerView(mRecyclerView); mRecyclerView.setAdapter(mAdapter); swipeRefresh.setOnRefreshListener(this); } @Override protected void onStart() { super.onStart(); loadData(); } @Override public void onRefresh() { new Handler().postDelayed(new Runnable() { @Override public void run() { swipeRefresh.setRefreshing(false); loadData(); } },2000); } @Override public void onLoadMore() { mAdapter.setProgressMore(true); new Handler().postDelayed(new Runnable() { @Override public void run() { itemList.clear(); mAdapter.setProgressMore(false); int start = mAdapter.getItemCount(); int end = start + 15; for (int i = start + 1; i <= end; i++) { itemList.add(new Item("Item " + i)); } mAdapter.addItemMore(itemList); mAdapter.setMoreLoading(false); } },2000); } private void loadData() { itemList.clear(); for (int i = 1; i <= 20; i++) { itemList.add(new Item("Item " + i)); } mAdapter.addAll(itemList); } }
Run you Project
At last, you can try to run this project and test the refresh feature that just implement.