Android RecyclerView的刷新分頁的實現(xiàn)
在開發(fā)中常常使用到刷新分頁,這里實現(xiàn)一個 RecyclerView 的簡單的刷新分頁操作,測試效果見文末,實現(xiàn)過程參考如下:
實現(xiàn)思路
- 加載更多數(shù)據(jù)使用到 RecyclerView 加載多種布局,根據(jù) ViewType 判斷加載數(shù)據(jù) Item 還是加載 FooterItem ;
- 通過線程模擬加載數(shù)據(jù);
- 為 RecyclerView 添加 addOnScrollListener 事件來監(jiān)聽用戶的滑動操作;
- 根據(jù)用戶滑動狀態(tài)以及具體情況開始加載數(shù)據(jù)
- 通知數(shù)據(jù)更新;
如何獲得 firstVisibleItemPosition
為了能夠在數(shù)據(jù)加載中動態(tài)判斷什么時候加載數(shù)據(jù),需要知道屏幕上顯示的第一個可見的 Item 的位置,當然了這里使用的是布局管理器是 LinearLayoutManager ,這樣查找屏幕上第一個可見的 Item 就顯得容易多了,下面介紹一些 LinearLayoutManager 的四個方法:
findFirstVisibleItemPosition()
獲得屏幕上第一個可見 Item 的 position,只要該 Item 有一部分可見,那么返回的 position 就是該Item 的 position。
findFirstCompletelyVisibleItemPosition()
獲得屏幕上第一個完整可見的 Item 的 position,只要該 Item 有一部分不可見,那么返回的 position 就是該 Item 對應的下一個能顯示完整的 Item 的position。
findLastVisibleItemPosition()
獲得屏幕上最后一個可見 Item 的 position,只要該 Item 有一部分可見,那么返回的 position 就是該Item 的 position。
findLastCompletelyVisibleItemPosition()
獲得屏幕上最后一個完整可見的 Item 的 position,只要該 Item 有一部分不可見,那么返回的 position 就是該 Item 對應的上一個能顯示完整的 Item 的position。
準備數(shù)據(jù)
/** * 初始化數(shù)據(jù) * @return */ public void initData(){ for (int i=0;i<30;i++){ arrayList.add("第"+i+"條數(shù)據(jù)"); } } /** * 線程模擬加載數(shù)據(jù) */ class LoadDataThread extends Thread{ @Override public void run() { initData(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } //通知主線程更新數(shù)據(jù) Message message = handler.obtainMessage(); message.what = UPDATE_DATA; message.obj = arrayList; handler.sendMessage(message); } }
代碼參考
主布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.manu.mrecyclerview.MainActivity"> <android.support.v7.widget.RecyclerView android:id="@+id/rv" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v7.widget.RecyclerView> </LinearLayout>
Item布局
/**item.xml**/ <?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="match_parent" android:padding="5dp"> <TextView android:id="@+id/tv_recycle" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:text="data" android:background="#cac3c3" android:padding="10dp" android:textSize="20sp"/> </LinearLayout>
/**item_footer.xml**/ <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal"> <ProgressBar style="?android:attr/progressBarStyleSmall" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/progressBar" /> <TextView android:text="正在努力加載中,請稍后..." android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/textView" /> </LinearLayout>
Adapter
這里使用了 RecyclerView 根據(jù)不同的 ViewType 加載多種布局的用法,使用時根據(jù)不同的布局創(chuàng)建不同的 ViewHolder , 然后根據(jù)不同的 Viewholder 為對應的 Item 添加數(shù)據(jù),注意 getItemViewType() 方法的用法,Adapter 代碼參考如下:
/** * Created by jzman on 2017/6/04 * RecycleView的Adapter */ public class RvAdapter1 extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements View.OnClickListener{ private static final int ITEM_FOOTER = 0x1; private static final int ITEM_DATA = 0x2; private Context mContext; private RecyclerView recyclerView; private ArrayList<String> mList; public RvAdapter1() {} public RvAdapter1(Context mContext, ArrayList<String> mList) { this.mContext = mContext; this.mList = mList; } public void setmList(ArrayList<String> mList) { this.mList = mList; } /** * 用于創(chuàng)建ViewHolder * @param parent * @param viewTypez * @return */ @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View view ; RecyclerView.ViewHolder vh = null; switch (viewType){ case ITEM_DATA: view = LayoutInflater.from(mContext).inflate(R.layout.item,null); view.setOnClickListener(this); vh = new DataViewHolder(view); //使用代碼設置寬高(xml布局設置無效時) view.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); break; case ITEM_FOOTER: view = LayoutInflater.from(mContext).inflate(R.layout.item_footer,null); //使用代碼設置寬高(xml布局設置無效時) vh = new FooterViewHolder(view); view.setLayoutParams(new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); break; } return vh; } /** * 獲取Item的View類型 * @param position * @return */ @Override public int getItemViewType(int position) { //根據(jù) Item 的 position 返回不同的 Viewtype if (position == (getItemCount())-1){ return ITEM_FOOTER; }else{ return ITEM_DATA; } } /** * 綁定數(shù)據(jù) * @param holder * @param position */ @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof DataViewHolder){ DataViewHolder dataViewHolder = (DataViewHolder) holder; dataViewHolder.tv_data.setText(mList.get(position)); }else if (holder instanceof FooterViewHolder){ } } /** * 選項總數(shù) * @return */ @Override public int getItemCount() { return mList.size()+1; } @Override public void onClick(View view) { //根據(jù)RecyclerView獲得當前View的位置 int position = recyclerView.getChildAdapterPosition(view); //程序執(zhí)行到此,會去執(zhí)行具體實現(xiàn)的onItemClick()方法 if (onItemClickListener!=null){ onItemClickListener.onItemClick(recyclerView,view,position,mList.get(position)); } } /** * 創(chuàng)建ViewHolder */ public static class DataViewHolder extends RecyclerView.ViewHolder{ TextView tv_data; public DataViewHolder(View itemView) { super(itemView); tv_data = (TextView) itemView.findViewById(R.id.tv_recycle); } } /** * 創(chuàng)建footer的ViewHolder */ public static class FooterViewHolder extends RecyclerView.ViewHolder{ public FooterViewHolder(View itemView) { super(itemView); } } private OnItemClickListener onItemClickListener; public void setOnItemClickListener(OnItemClickListener onItemClickListener){ this.onItemClickListener = onItemClickListener; } /** * 定義RecyclerView選項單擊事件的回調(diào)接口 */ public interface OnItemClickListener{ //參數(shù)(父組件,當前單擊的View,單擊的View的位置,數(shù)據(jù)) void onItemClick(RecyclerView parent,View view, int position, String data); } /** * 將RecycleView附加到Adapter上 */ @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { super.onAttachedToRecyclerView(recyclerView); this.recyclerView= recyclerView; } /** * 將RecycleView從Adapter解除 */ @Override public void onDetachedFromRecyclerView(RecyclerView recyclerView) { super.onDetachedFromRecyclerView(recyclerView); this.recyclerView = null; } }
MainActivity
這里主要注意 rv.addOnScrollListener(new OnScrollListener() ...里面的具體實現(xiàn),MainActivity 代碼參考如下:
/** * Created by jzman on 2017/6/04 0013. */ public class MainActivity extends AppCompatActivity { private static final int UPDATE_DATA = 0x3; private RecyclerView rv; RvAdapter1 adapter; private ArrayList<String> arrayList = new ArrayList<>(); //加載更多數(shù)據(jù)時最后一項的索引 private int lastLoadDataItemPosition; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); rv = (RecyclerView) findViewById(R.id.rv); //設置布局管理器 rv.setLayoutManager(new LinearLayoutManager(this));//線性 // rv.setLayoutManager(new GridLayoutManager(this,4));//線性 // rv.setLayoutManager(new StaggeredGridLayoutManager(4,StaggeredGridLayoutManager.VERTICAL));//線性 initData(); adapter = new RvAdapter1(this,arrayList); adapter.setOnItemClickListener(new RvAdapter1.OnItemClickListener() { @Override public void onItemClick(RecyclerView parent, View view, int position, String data) { Toast.makeText(MainActivity.this, data, Toast.LENGTH_SHORT).show(); } }); rv.addOnScrollListener(new OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { if (newState == SCROLL_STATE_IDLE && lastLoadDataItemPosition == adapter.getItemCount()){ new LoadDataThread().start(); } } @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof LinearLayoutManager){ LinearLayoutManager manager = (LinearLayoutManager) layoutManager; int firstVisibleItem = manager.findFirstVisibleItemPosition(); int l = manager.findLastCompletelyVisibleItemPosition(); lastLoadDataItemPosition = firstVisibleItem+(l-firstVisibleItem)+1; } } }); rv.setAdapter(adapter); } /** * 初始化數(shù)據(jù) * @return */ public void initData(){ for (int i=0;i<25;i++){ arrayList.add("第"+i+"條數(shù)據(jù)"); } } /** * 線程模擬加載數(shù)據(jù) */ class LoadDataThread extends Thread{ @Override public void run() { initData(); try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } Message message = handler.obtainMessage(); message.what = UPDATE_DATA; message.obj = arrayList; handler.sendMessage(message); } } private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case UPDATE_DATA: arrayList = (ArrayList<String>) msg.obj; adapter.setmList(arrayList); adapter.notifyDataSetChanged(); break; } } }; }
測試效果
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- Android自定義ListView實現(xiàn)下拉刷新上拉加載更多
- android RecycleView實現(xiàn)下拉刷新和上拉加載
- 解決android viewmodel 數(shù)據(jù)刷新異常的問題
- Android巧用XListView實現(xiàn)萬能下拉刷新控件
- Android自定義view仿微信刷新旋轉小風車
- Android自定義控件ListView下拉刷新的代碼
- Android ExpandableListView實現(xiàn)下拉刷新和加載更多效果
- android使用SwipeRefreshLayout實現(xiàn)ListView下拉刷新上拉加載
- android使用PullToRefresh框架實現(xiàn)ListView下拉刷新上拉加載更多
- Android 中RecyclerView頂部刷新實現(xiàn)詳解
- Android四種方式刷新View的操作方法
相關文章
Android開發(fā)之圖形圖像與動畫(一)Paint和Canvas類學習
Paint類代表畫筆,用來描述圖形的顏色和風格,如線寬,顏色,透明度和填充效果等信息;Canvas類代表畫布,通過該類提供的構造方法,可以繪制各種圖形;感興趣的朋友可以了解下啊,希望本文對你有所幫助2013-01-01Android 中為什么要用Fragment.setArguments(Bundle bundle)來傳遞參數(shù)
這篇文章主要介紹了Android 中為什么要用Fragment.setArguments(Bundle bundle)來傳遞參數(shù),非常不錯,具有參考借鑒價值,需要的朋友參考下2017-01-01Android列表組件ListView使用詳解之動態(tài)加載或修改列表數(shù)據(jù)
今天小編就為大家分享一篇關于Android列表組件ListView使用詳解之動態(tài)加載或修改列表數(shù)據(jù),小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03Android實現(xiàn)省市區(qū)三級聯(lián)動
這篇文章主要為大家詳細介紹了Android實現(xiàn)省市區(qū)三級聯(lián)動,Spinner實現(xiàn)省市區(qū)的三級聯(lián)動,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-07-07Android 自定義ProgressDialog進度條對話框用法詳解
ProgressDialog為進度對話框。android手機自帶的對話框顯得比較單一,我們可以通過ProgressDialog來自己定義對話框中將要顯示出什么東西2016-01-01