【版權申明】非商業目的註明出處可自由轉載
博文地址:
出自:shusheng007
前言
在日常從事Android開發工作時,經常會遇到下拉刷新列表頁面,上拉自動加載列表的需求, GitHub上已經有很多關於這方面的功能極其強大的類庫了,那我們還有必要自己寫一個嗎?
答案是:也許。因爲那些類庫實在是太重了!很多時候我們只使用了其5%的功能,但卻不得不忍受剩下那95%的“無用”功能和複雜性。
UI方面,自己實現某些效果很多時候比直接使用現存類庫更合適,關於這個話題這個不能深槓,世界上沒有最好的東西,只有最適合的東西。
今天我們就簡單介紹如何快速寫一個一個既可下拉刷新,又可上滑無限加載的小巧靈活的UI控件。
InfiniteRecyclerView
一般情況下我們只使用Android原生提供的那些控件稍作組合或修改即可完成絕大部分UI需求,讓我們看一下如何通過簡單的組合Android原生的 SwipeRefreshLayout
和RecyclerView
來製作一個非常輕量而實用的控件。
下圖只演示了無限加載功能:
準備實現的實用功能
- 下滑可以刷新頁面
- 上滑可以無限加載
其實日常工作需求最多的也就上面兩條。
實現思想
-
使用
SwipeRefreshLayout
套一個RecyclerView
,如下所示<androidx.swiperefreshlayout.widget.SwipeRefreshLayout android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycle_view" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"/> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
SwipeRefreshLayout
負責下滑刷新,RecyclerView
, 負責上滑加載 -
通過
RecyclerView
的RecyclerView.OnScrollListener
來監聽是否滑動到了最後一個item,如果滑動到了最後一個item則觸發加載更多操作。private class OnScrollToBottomListener extends RecyclerView.OnScrollListener { @Override public void onScrolled(RecyclerView recyclerView, int dx, int dy) { ... if (manager instanceof LinearLayoutManager) { int lastCompletelyVisibleItemPosition = ((LinearLayoutManager) manager).findLastCompletelyVisibleItemPosition(); if (adapter.getItemCount() > 1 && lastCompletelyVisibleItemPosition >= adapter.getItemCount() - 1) { adapter.loadingMore(); } } else if (manager instanceof StaggeredGridLayoutManager) { int[] itemPositions = new int[2]; ((StaggeredGridLayoutManager) manager).findLastVisibleItemPositions(itemPositions); int lastVisibleItemPosition = (itemPositions[1] != 0) ? ++itemPositions[1] : ++itemPositions[0]; if (lastVisibleItemPosition >= adapter.getItemCount()) { adapter.loadingMore(); } } } ... }
- 當處於加載過程中時,在最後一行展示一個加載更多的 view
具體實現我覺得還是的自己看源代碼吧,源代碼就是我們程序員有效交流的最好語言。
如何使用
第一步:自定義一個
Adapter
,其需要繼承RefreshRecycleAdapter<T>
, 例如下面這樣public class BeautyListAdapter extends RefreshRecycleAdapter<Beauty> { public BeautyListAdapter(List<Beauty> dataSource) { super(dataSource); } @Override public RecyclerView.ViewHolder onCreateCustomViewHolder(ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_beauty,parent,false); return new BeautyViewHolder(view); } @Override public void onBindCustomViewHolder(RecyclerView.ViewHolder holder, int position) { BeautyViewHolder beautyViewHolder= (BeautyViewHolder) holder; final Beauty beauty=getList().get(position); beautyViewHolder.binding.ivBeautyHead.setImageResource(beauty.getPhotoId()); beautyViewHolder.binding.tvBeautyTitle.setText(beauty.getName()); beautyViewHolder.binding.tvBeautyIntroduction.setText(beauty.getIntroduction()); } static class BeautyViewHolder extends RecyclerView.ViewHolder{ private final ItemBeautyBinding binding; public BeautyViewHolder(@NonNull View itemView) { super(itemView); binding= ItemBeautyBinding.bind(itemView); } } }
Note:上面的代碼使用了
viewBinding
功能,對此不熟悉的同學,推薦閱讀Android開發之秒懂ViewBinding,一代神器ButterKnife的終結者第二步: 初始化控件併爲其設置
Adapter
和LayoutManager
mAdapter = new BeautyListAdapter(mViewModel.dataSource); mBinding.pullRefreshList.setLayoutManager(new LinearLayoutManager(context)); mBinding.pullRefreshList.setAdapter(mAdapter); mAdapter.setOnRefreshLoadMoreListener(new AdapterLoader.OnRefreshLoadMoreListener() { @Override public void onRefresh() { //此處調用刷新邏輯 } @Override public void onLoadMore() { //此處調用加載更多邏輯 } });
第三步:處理結果
- 當刷新完成後使用如下代碼告知控件刷新完成,去掉刷新的標誌
mBinding.pullRefreshList.setRefresh(false);
- 當加載一頁完成後,向數據源增加數據並刷新視圖
mAdapter.notifyDataSetChanged();
當返回的列表爲空時,說明已經沒有數據了,此時使用如下方法通知控件已經到底了
mAdapter.setHasMore(false);
優勢
- 輕量級
- 強可擴展性
你完全可以獲取到SwipeRefreshLayout
和RecyclerView
,然後對他們進行各種騷操作。 - 使用簡單,與
RecyclerView
的使用方法保持一致,只要會用RecyclerView
就可輕鬆使用(如果你說你只會用ListView,不會用RecyclerView,我只能對你漏出鄙夷的微笑了)。
總結
2020年突入其來的新冠病毒疫情已經肆虐了4個月了,很多受疫情影響的公司都快撐不住了,身邊開始出現很多被裁員的同事和朋友,前兩天親眼目睹了一位被裁的同事情緒崩潰的樣子,這件事也給自己敲響了警鐘,單純出賣自己的時間真的是一件很危險的事情,還是要不斷的使自己增值,同時去找一件自己喜歡的事情,並堅持做下去。
耳邊又想起了那個什麼夫斯基的《鋼鐵是怎樣煉成的》:
當他回首往事的時候,他不會因虛度年華而悔恨,也不會因碌碌無爲而羞恥!
當我們回首往事的時候,往往會遺憾沒有做過的事情,而不會悔恨做了什麼事情。
源代碼下載地址:InfiniteRecyclerview