很想給大家分享這個開源專案,但是由於工作的關係,沒有抽出空,但還是趁著工作間隙寫下了這篇部落格。
簡介
LRecyclerView是支援addHeaderView、 addFooterView、下拉重新整理、分頁載入資料的RecyclerView。
它對 RecyclerView 控制元件進行了擴充,給RecyclerView增加HeaderView、FooterView,並且不需要對你的Adapter做任何修改。
主要功能
- 下拉重新整理、滑動到底部自動載入下頁資料;
- 可以方便新增Header和Footer;
- 頭部下拉樣式可以自定義;
- 具備item點選和長按事件。
- 網路錯誤載入失敗點選Footer重新請求資料;
- 可以動態為FooterView賦予不同狀態(載入中、載入失敗、滑到最底等)。
專案地址:https://github.com/jdsjlzx/LRecyclerView
感謝
如果我比別人看得遠些,那是因為我站在巨人們的肩上。 (牛頓)
本開源控制元件是基於 HeaderAndFooterRecyclerView 開源專案而來,在原基礎上進行了擴充。在此感謝cundong作者(github地址:https://github.com/cundong)。
效果圖
Gradle
Step 1. 在你的根build.gradle檔案中增加JitPack倉庫依賴。
1 2 3 4 5 6 |
allprojects { repositories { jcenter() maven { url "https://jitpack.io" } } } |
Step 2. 在你的model的build.gradle檔案中增加LRecyclerView依賴。
1 |
compile 'com.github.jdsjlzx:LRecyclerView:1.0.0' |
使用
新增HeaderView、FooterView
1 2 3 4 5 6 7 8 9 10 11 12 13 |
mDataAdapter = new DataAdapter(this); mDataAdapter.setData(dataList); mHeaderAndFooterRecyclerViewAdapter = new HeaderAndFooterRecyclerViewAdapter(this, mDataAdapter); mRecyclerView.setAdapter(mHeaderAndFooterRecyclerViewAdapter); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); //add a HeaderView RecyclerViewUtils.setHeaderView(mRecyclerView, new SampleHeader(this)); //add a FooterView RecyclerViewUtils.setFooterView(mRecyclerView, new SampleFooter(this)); |
注意:
mHeaderAndFooterRecyclerViewAdapter = new HeaderAndFooterRecyclerViewAdapter(this, mDataAdapter);
HeaderAndFooterRecyclerViewAdapter提供了一些實用的功能,使用者不用關心它的實現,只需構造的時候把自己的mDataAdapter以引數形式傳進去即可。
下拉重新整理和載入更多
為了大家使用方便,將需要用的方法統一封裝到介面LScrollListener中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
mRecyclerView.setLScrollListener(new LRecyclerView.LScrollListener() { @Override public void onRefresh() { } @Override public void onScrollUp() { } @Override public void onScrollDown() { } @Override public void onBottom() { } @Override public void onScrolled(int distanceX, int distanceY) { } }); |
LScrollListener實現了nRefresh()、onScrollUp()、onScrollDown()、onBottom()、onScrolled五個事件,如下所示:
1 2 3 4 5 6 7 8 9 |
void onRefresh();//pull down to refresh void onScrollUp();//scroll down to up void onScrollDown();//scroll from up to down void onBottom();//load next page void onScrolled(int distanceX, int distanceY);// moving state,you can get the move distance |
- onRefresh()——RecyclerView下拉重新整理事件;
- onScrollUp()——RecyclerView向上滑動的監聽事件;
- onScrollDown()——RecyclerView向下滑動的監聽事件;
- onBottom()——RecyclerView滑動到底部的監聽事件;
- onScrollDown()——RecyclerView正在滾動的監聽事件;
載入更多(載入下頁資料)
從上面的LScrollListener介紹中就可以看出,實現載入更多隻要在onBottom()介面中處理即可。
下拉重新整理
為了達到和Listview的下拉重新整理效果,本專案沒有藉助SwipeRefreshLayout控制元件,而是在自定義RecyclerView頭部實現的重新整理效果。
這裡的下拉重新整理效果借鑑了開源庫:AVLoadingIndicatorView
設定載入樣式:
1 2 |
mRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader); mRecyclerView.setArrowImageView(R.drawable.iconfont_downgrey); |
AVLoadingIndicatorView庫有多少效果,LRecyclerView就支援多少下拉重新整理效果,當然你也可以自定義下拉效果。
效果圖:
下拉重新整理邏輯處理:
從上面的LScrollListener介紹中就可以看出,實現下拉重新整理只要在onRefresh()介面中處理即可。
載入網路異常處理
載入資料時如果網路異常或者斷網,LRecyclerView為你提供了重新載入的機制。
效果圖:
網路異常出錯程式碼處理如下:
1 2 3 4 5 6 7 8 9 |
RecyclerViewStateUtils.setFooterViewState(getActivity(), mRecyclerView, getPageSize(), LoadingFooter.State.NetWorkError, mFooterClick); private View.OnClickListener mFooterClick = new View.OnClickListener() { @Override public void onClick(View v) { RecyclerViewStateUtils.setFooterViewState(getActivity(), mRecyclerView, getPageSize(), LoadingFooter.State.Loading, null); requestData(); } }; |
上面的mFooterClick就是我們點選底部的Footer時的邏輯處理事件,很顯然我們還是在這裡做重新請求資料操作。
點選事件和長按事件處理
在Hongyang前輩的部落格中有下描述:
Click and LongClick
不過一個挺鬱悶的地方就是,系統沒有提供ClickListener和LongClickListener。
不過我們也可以自己去新增,只是會多了些程式碼而已。
實現的方式比較多,你可以通過mRecyclerView.addOnItemTouchListener去監聽然後去判斷手勢, 當然你也可以通過adapter中自己去提供回撥,這裡我們選擇後者,前者的方式,大家有興趣自己去實現。
出自:http://blog.csdn.net/lmj623565791/article/details/45059587
Hongyang大神選擇了後者,LRecyclerView早期選擇了前者,經過實踐總結,在adapter中實現點選事件會好點。
先看下怎麼使用:
1 2 3 4 5 6 7 8 9 10 11 |
mHeaderAndFooterRecyclerViewAdapter.setOnItemClickLitener(new OnItemClickLitener() { @Override public void onItemClick(View view, int position) { } @Override public void onItemLongClick(View view, int position) { } }); |
原理就是實現viewHolder.itemView的點選和長按事件。由於程式碼過多就不貼出來了。
viewHolder.itemView是RecyclerView.Adapter中本身就具有的,不用額外定義。
原始碼如下:
1 2 3 4 5 6 7 |
public static abstract class ViewHolder { public final View itemView; int mPosition = NO_POSITION; int mOldPosition = NO_POSITION; long mItemId = NO_ID; int mItemViewType = INVALID_TYPE; int mPreLayoutPosition = NO_POSITION; |
設定空白View(setEmptyView)
1 |
mRecyclerView.setEmptyView(view); |
注意佈局檔案:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <com.cundong.recyclerview.LRecyclerView android:id="@+id/list" android:layout_width="fill_parent" android:layout_height="fill_parent"/> <include android:id="@+id/empty_view" layout="@layout/layout_empty" android:visibility="gone"/> </RelativeLayout> |
分享
介紹完了LRecyclerView,似乎還少些什麼,對了,那就是adapter了。
為了方便大家使用,分享個封裝過的adapter。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
public class ListBaseAdapter<T extends Entity> extends RecyclerView.Adapter { protected Context mContext; protected int mScreenWidth; public void setScreenWidth(int width) { mScreenWidth = width; } protected ArrayList<T> mDataList = new ArrayList<>(); @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { } @Override public int getItemCount() { return mDataList.size(); } public List<T> getDataList() { return mDataList; } public void setDataList(Collection<T> list) { this.mDataList.clear(); this.mDataList.addAll(list); notifyDataSetChanged(); } public void addAll(Collection<T> list) { int lastIndex = this.mDataList.size(); if (this.mDataList.addAll(list)) { notifyItemRangeInserted(lastIndex, list.size()); } } public void clear() { mDataList.clear(); notifyDataSetChanged(); } } |
ListBaseAdapter使用了泛型,簡單方便,消除了強制型別轉換。
使用如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
private class DataAdapter extends ListBaseAdapter<ItemModel>{ private LayoutInflater mLayoutInflater; public DataAdapter(Context context) { mLayoutInflater = LayoutInflater.from(context); mContext = context; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new ViewHolder(mLayoutInflater.inflate(R.layout.sample_item_text, parent, false)); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { ItemModel item = mDataList.get(position); ViewHolder viewHolder = (ViewHolder) holder; viewHolder.textView.setText(item.title); } private class ViewHolder extends RecyclerView.ViewHolder { private TextView textView; public ViewHolder(View itemView) { super(itemView); textView = (TextView) itemView.findViewById(R.id.info_text); } } } |
ListBaseAdapter雖然功能不強大,但是使用很方便。
結語
LRecyclerView使用方便簡單,無論你新增多少Header和Footer,你都不用擔心position的問題,除了方便還是方便。
最後再介紹下專案地址:https://github.com/jdsjlzx/LRecyclerView
如果覺得上面的例子UI簡單,這裡再分享個公司專案:https://github.com/jdsjlzx/Community
效果圖:
如果大家使用過程中有任何問題,請留言,我會及時修正。
後記:如果後續再增加功能,請詳細看github上面的專案介紹,將不在部落格裡面更新。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式