Pagination merupakan suatu metode yang digunakan untuk membatasi data yang ditampilkan. Dengan menerapkan pagination, maka jumlah data yang ditampilkan per halamannya dibatasi, sehingga tidak perlu langsung mengambil semua data. Pada tutorial kali ini saya akan membahas cara menerapkan pagination di RecyclerView. Untuk itu saya anjurkan untuk melihat postingan saya tentang (Tutorial Android) RecyclerView and CardView Android Material Design
Oke kita akan menggunakan project dari postingan sebelumnya, hanya kita akan modifikasi sedikit.
Pertama, buat layout untuk menampilkan progressbar. Progressbar akan muncul dibagian bawah list ketika di scroll.
footer_loading.xml
Selanjutnya kita akan menambahkan progressbar tadi sebagai footer di RecyclerView. Modifikasi kelas MemberListAdapter.java berikut.
package wim.example.com.androidpaging.adapter; package wim.example.com.androidpaging.adapter; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; import java.util.ArrayList; import java.util.List; import wim.example.com.androidpaging.R; import wim.example.com.androidpaging.model.Member; /** * Created by wim on 4/6/16. */ public class MemberListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private final int VIEW_TYPE_ITEM = 0; private final int VIEW_TYPE_LOADING = 1; private boolean loading = true; private List<Member> memberList; private OnItemClickListener onItemClickListener; public MemberListAdapter() { memberList = new ArrayList<>(); } private void add(Member item) { memberList.add(item); notifyItemInserted(memberList.size()); } public void addAll(List<Member> memberList) { for (Member member : memberList) { add(member); } } public void remove(Member item) { int position = memberList.indexOf(item); if (position > -1) { memberList.remove(position); notifyItemRemoved(position); } } public void clear() { while (getItemCount() > 0) { remove(getItem(0)); } } public Member getItem(int position){ return memberList.get(position); } @Override public int getItemViewType (int position) { if(isPositionFooter (position)) { return VIEW_TYPE_LOADING; } return VIEW_TYPE_ITEM; } private boolean isPositionFooter (int position) { return position == memberList.size(); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == VIEW_TYPE_ITEM) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_member, parent, false); return new MemberViewHolder(view, onItemClickListener); } else if (viewType == VIEW_TYPE_LOADING) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.footer_loading, parent, false); return new LoadingViewHolder(view); } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof MemberViewHolder) { MemberViewHolder memberViewHolder = (MemberViewHolder) holder; final Member member = memberList.get(position); memberViewHolder.memberThumb.setImageResource(member.getThumb()); memberViewHolder.memberName.setText(member.getName()); memberViewHolder.memberTeam.setText(member.getTeam()); } else if (holder instanceof LoadingViewHolder) { LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder; loadingViewHolder.progressBar.setIndeterminate(true); loadingViewHolder.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE); } } public void setLoading(boolean loading){ this.loading = loading; } @Override public int getItemCount() { return memberList == null ? 0 : memberList.size() + 1; } @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); } @Override public void onDetachedFromRecyclerView(RecyclerView recyclerView) { super.onDetachedFromRecyclerView(recyclerView); } public void setOnItemClickListener(OnItemClickListener onItemClickListener) { this.onItemClickListener = onItemClickListener; } static class MemberViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { ImageView memberThumb; TextView memberName; TextView memberTeam; OnItemClickListener onItemClickListener; public MemberViewHolder(View itemView, OnItemClickListener onItemClickListener) { super(itemView); memberThumb = (ImageView) itemView.findViewById(R.id.thumb); memberName = (TextView) itemView.findViewById(R.id.name); memberTeam = (TextView) itemView.findViewById(R.id.team); itemView.setOnClickListener(this); this.onItemClickListener = onItemClickListener; } @Override public void onClick(View v) { onItemClickListener.onItemClick(v, getAdapterPosition()); } } static class LoadingViewHolder extends RecyclerView.ViewHolder { public ProgressBar progressBar; public LoadingViewHolder(View itemView) { super(itemView); progressBar = (ProgressBar) itemView.findViewById(R.id.loading); } } public interface OnItemClickListener { void onItemClick(View view, int position); } }
Lalu kita akan mengimplementasikan pagination dengan RecyclerView.OnScrollListener pada RecyclerView.
private RecyclerView.OnScrollListener recyclerViewOnScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); int visibleItemCount = linearLayoutManager.getChildCount(); int totalItemCount = linearLayoutManager.getItemCount(); int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition(); if (!isLoading && !isLastPage) { if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0 && totalItemCount >= PAGE_SIZE) { isLoading = true; // load more data here } } } };
Lalu modifikasi kelas MemberFragment.java berikut.
package wim.example.com.androidpaging.fragments; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import wim.example.com.androidpaging.R; import wim.example.com.androidpaging.adapter.MemberListAdapter; import wim.example.com.androidpaging.model.Member; /** * Created by wim on 4/5/16. */ public class MemberFragment extends Fragment { private int PAGE_SIZE = 6; private boolean isLastPage = false; private boolean isLoading = false; private RecyclerView listMember; private LinearLayoutManager linearLayoutManager; private MemberListAdapter memberListAdapter; protected Context context; int thumb[] = {R.drawable.acha, R.drawable.yupi, R.drawable.della, R.drawable.kinal, R.drawable.uty, R.drawable.shafa, R.drawable.hanna, R.drawable.lidya, R.drawable.nadila, R.drawable.nat, R.drawable.sisil, R.drawable.viny, R.drawable.chika_chan, R.drawable.ikha, R.drawable.ayen, R.drawable.saktia, R.drawable.dudut, R.drawable.yona}; String name[] = {"Alicia Chanzia", "Cindy Yuvia", "Della Delila", "Devi Kinal Putri", "Dwi Putri Bonita", "Fakhriyani Shafariyanti", "Jennifer Hanna", "Lidya Maulida Djuhandar", "Nadila Cindi Wantari", "Natalia", "Priscillia Sari Dewi", "Ratu Vienny Fitrilya", "Rina Chikano", "Riskha Fairunissa", "Rona Anggreani", "Saktia Oktapyani", "Sinka Juliani", "Viviyona Apriani"}; String motto[] = {"Hap!Tangkap Aku!", "Mau Kemana Kita?", "Future Processor", "K3bahagiaan Depi", "Different", "Shafa Disana?", "Target", "Banyak Mau", "Yossha Ikuzo!", "Spicy Hot", "Yuk Isi Batre Senter", "#KitaBisa", "Yuk.. Kita Dangdutan!", "Nothing Gonna Stop Us Now", "Stand Up!", "Saktia Dalam Jiwa", "Berarti Dalam Hidup", "Life In Technicolor"}; public static MemberFragment newInstance(){ return new MemberFragment(); } @Override public void onAttach(Context context) { super.onAttach(context); this.context = context; } @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_member, container, false); listMember = (RecyclerView) rootView.findViewById(R.id.listMember); return rootView; } @Override public void onActivityCreated(@Nullable Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); linearLayoutManager = new LinearLayoutManager(context); memberListAdapter = new MemberListAdapter(); listMember.setLayoutManager(linearLayoutManager); listMember.setAdapter(memberListAdapter); listMember.addOnScrollListener(recyclerViewOnScrollListener); initData(); initListener(); } private void initData(){ List<Member> memberList = new ArrayList<>(); Member member; for(int i=0; i < PAGE_SIZE; i++){ member = new Member(); member.setId(i+1); member.setName(name[i]); member.setTeam(motto[i]); member.setThumb(thumb[i]); memberList.add(member); } memberListAdapter.addAll(memberList); } private void loadData(){ isLoading = false; List<Member> memberList = new ArrayList<>(); Member member; int index = memberListAdapter.getItemCount() - 1; int end = index + PAGE_SIZE; if (end <= thumb.length) { for (int i = index; i < end; i++) { member = new Member(); member.setId(i + 1); member.setName(name[i]); member.setTeam(motto[i]); member.setThumb(thumb[i]); memberList.add(member); } memberListAdapter.addAll(memberList); if(end >= thumb.length){ memberListAdapter.setLoading(false); } } } private void initListener() { memberListAdapter.setOnItemClickListener(new MemberListAdapter.OnItemClickListener() { @Override public void onItemClick(View view, int position) { Toast.makeText(context, "Clicked at index "+ position, Toast.LENGTH_SHORT).show(); } }); } @Override public void onDestroyView() { super.onDestroyView(); } private RecyclerView.OnScrollListener recyclerViewOnScrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); int visibleItemCount = linearLayoutManager.getChildCount(); int totalItemCount = linearLayoutManager.getItemCount(); int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition(); if (!isLoading && !isLastPage) { if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount && firstVisibleItemPosition >= 0 && totalItemCount >= PAGE_SIZE) { isLoading = true; new Handler().postDelayed(new Runnable() { @Override public void run() { loadData(); } }, 2000); } } } }; }
Deploy dan jalankan maka hasilnya seperti ini, terlihat progressbar dibagian bawah.
*sory kalau TS nya ngidol :v
Source code lengkap dapat dilihat di https://github.com/wimsonevel/AndroidPagingRecyclerView
Sekian dan semoga bermanfaat.
Happy Coding :)
13 Komentar
Terima kasih mas
Balasizin di coba ya..
ok gan
BalasMas bila pada recyclerviewnya saat diklik?setonclicklinstener maka akan menampilkan detail datanya, apa ada tutorialnya. Makasih
Balasada gan. Coba lihat di sini ada contoh recyclerview bisa di klik http://wimsonevel.blogspot.co.id/2016/05/tutorial-android-tutorial-crud-with.html
BalasUntuk RecyclerView yang ini untuk menambahkan aksi click bagaimana mas?
BalasNamba coding dibagian mana saja?
Thanks
udah ditambahkan ditutorial di atas gan.. bisa dicek lagi..
Balasemm mas apa fungsi variable isLoading dan isLastPage ?? kok kayaknya gak di pake buat apa apa deh ??
Balasyang di bagian method onScrolled expresi pertama yang "isLoading && isLastPage" kayaknya gak perlu di pake juga bisa deh soalnya udah pasti hasil akan selalu false.
iya gan cuma pengecekan tambahan aja hehe.., kalau datanya dinamis misal dari API baru pake itu gan..
Balasmas, kalo saya implementasikan load data dari server.
Balasitu berarti diwebnya gak perlu dibuat paging atau bgmana?
btw tQ semua artikel nya bagus
di web gak perlu, cukup select datanya per limit di database pake query.. nanti saya buatin tutorial load data dari server.. thanks :)
BalasTerima kasih mas, Tutorialnya berhasil. Tapi gimana kalo load data nya lewat Web Service? Untuk page per limitnya itu di setting di Adapternya atau lewat Database ya?
Balasdua2nya gan, setting limit di database, kalo page di adapter. Bisa dilihat contoh projectnya disini https://wimsonevel.blogspot.co.id/2017/07/re-tutorial-android-http-client-on.html
BalasPenulisan markup di komentar