課題
RecyclerViewの追加読み込み時にフッターを表示したい。
対策
リストの最後尾にFooter用のオブジェクトを追加し、ViewTypeで判別して出し分け。追加データ取得時に削除する。
エレガントな方法ではないけれど、とりあえず思いつく簡単な方法。
- 任意の型を持つFOOTER_VIEWを用意
- 追加読み込み時にAdd
- RecyclerView.Apadpter内ではViewTypeを判別してフッターに指定したViewTypeの時にFooterViewを返す。
- リクエストの戻りがきたらリストからFOOTER_VIEWを削除
//とあるFragmentでの作業を想定 public static final Integer FOOTER_VIEW = new Integer(1); private List mList; mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); //略 //リストの末尾に追加 LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager(); int lastItemPosition = manager.findLastVisibleItemPosition(); if (lastItemPosition >= manager.getItemCount() - 1) { Handler handler = new Handler(); handler.post(new Runnable() { @Override public void run() { mItems.add(AppConstants.VIEW_TYPE_FOOTER); mAdapter.notifyItemInserted(mItems.indexOf(AppConstants.VIEW_TYPE_FOOTER)); requestQuery(); //追加読み込み } }); } } @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); //do nothing } });
onScrolled内でnotifyItemInsertedを呼ぶと内部で例外が発生するのでHandlerを使ってタイミングを遅らせる。
RecyclerView.Apadpter内でgetItemViewTypeを使い、ViewTypeをうまいことやる。サンプルではinstanceofで見ているが別な方法もあるかと。
//RecyclerView.Apadpterの断片 @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v; int storeId = -1; RecyclerView.ViewHolder holder = null; switch (viewType) { case 1: v = mInflater.inflate(R.layout.list_item_header, parent, false); holder = new HeaderViewHolder(v); break; case 4: v = mInflater.inflate(R.layout.footer_loading, parent, false); holder = new FooterViewHolder(v); break; default: v = mInflater.inflate(R.layout.store_search_list_item, parent, false); holder = new StoreViewHolder(v); } return holder; } /** * ViewHolder for Store */ public class FooterViewHolder extends RecyclerView.ViewHolder { public FooterViewHolder(View itemView) { super(itemView); } } @Override public int getItemViewType(int position) { Object o = mResults.get(position); if (o instanceof String) { return 1; } else if (o instanceof Integer){ return 4; //footer or header; } return 0; }
追加のデータがきたらFOOTER_VIEWを削除する。
@Override public void success(Hoge hoge, Response response) { if ( mStoreList.contains(FOOTER_VIEW) ){ mStoreList.remove(FOOTER_VIEW); } }
リストのデータの末尾がフッターになる。アイテム件数が一時的に1件増えるので気をつける。