github源碼地址:https://github.com/zhou-you/EasyXRecyclerView
XRecyclerView使用介紹
XRecyclerView基于RecyclerView的封裝盆驹,在原有功能的基礎上支持刷新圆丹、加載更多、自定義刷新加載更多躯喇、添加頭部辫封、尾部等
添加(單個/多個)HeaderViw、FooterView
可以添加單個或者多個普通HeaderViw廉丽、FooterView,支持內(nèi)容為LinearLayoutManager和GridLayoutManager倦微。
方式一:
//添加一個頭部view
mRecyclerView.addHeaderView(new SampleHeader(this));
//mRecyclerView.addHeaderView(new SampleHeader2(this));//添加第二個頭部view
....
//mRecyclerView.addHeaderView(new SampleHeaderN(this));//添加第n個頭部view(多頭部)
//添加一個尾部view
mRecyclerView.addFooterView(new SampleFooter(this));
//mRecyclerView.addFooterView(new SampleFooter2(this));//添加第二個尾部view
....
//mRecyclerView.addFooterView(new SampleFooterN(this));//添加第n個尾部view(多尾部)
方式二:
//添加一個頭部view
View headerView = LayoutInflater.from(this).inflate(R.layout.layout_header, (ViewGroup)findViewById(android.R.id.content),false);
mRecyclerView.addHeaderView(headerView);
//mRecyclerView.addHeaderView(headerView2);//添加第二個頭部view
...
//mRecyclerView.addHeaderView(headerViewN);//添加第n個頭部view(多頭部)
//點擊事件
headerView.findViewById(R.id.test_txt).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
...
}
});
//添加一個尾部view
View footerView = getLayoutInflater().inflate(R.layout.layout_footer, (ViewGroup) mRecyclerView.getParent(), false);
mRecyclerView.addFooterView(footerView);
//mRecyclerView.addFooterView(footerView2);//添加第二個尾部view
....
//mRecyclerView.addFooterView(footerViewN);//添加第n個尾部view(多尾部)
//點擊事件
footerView.findViewById(R.id.test_txt).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
...
}
});
注:此功能只是添加普通的頭部和尾部,與刷新和加載更多的頭部和尾部是不一樣的正压,切記欣福!不會影響刷新頭和加載更多尾部的顯示問題
移除HeaderViw、FooterView
//移除添加的頭部view
mRecyclerView.removeHeaderView(headerView);
//移除添加的尾部view
mRecyclerView.removeFooterView(footerView);
下拉刷新和加載更多樣式
//設置下拉刷新Progress的樣式
mRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader); //在ProgressStyle里面選擇喜歡的樣式
//設置下拉刷新箭頭
mRecyclerView.setArrowImageView(R.drawable.iconfont_downgrey);
//設置加載更多Progress的樣式
mRecyclerView.setLoadingMoreProgressStyle(ProgressStyle.BallPulse);
注:1.如果采用自定義下拉刷新setRefreshHeader()和加載更多setLoadingMoreFoote()蔑匣,以上設置會不起作用劣欢,也無須設置。
開啟和禁止下拉刷新裁良、加載更多功能
//打開刷新和加載更多
mRecyclerView.setPullRefreshEnabled(true);
mRecyclerView.setLoadingMoreEnabled(true);
注:默認是開啟凿将。
設置底部加載文字提示
mRecyclerView.setFootViewText("拼命加載中","已經(jīng)全部");
注:自定義加載更多View時,此設置不起作用价脾,切記牧抵!
下拉刷新完成
mRecyclerView.refreshComplete();
上拉加載更多完成
mRecyclerView.loadMoreComplete();
數(shù)據(jù)加載完成
mRecyclerView.setNoMore(true);
開啟進入頁面自動刷新
mRecyclerView.setRefreshing(true);//沒有更多數(shù)據(jù)
例:在Acitvity中開啟進入頁面自動刷新狞山,在onStart()中處理碳褒。
@Override
protected void onStart() {
super.onStart();
if(mRecyclerView !=null){
mRecyclerView.setRefreshing(true);
}
}
自定義下拉刷新View
- 自定義view繼承BaseRefreshHeader盐固;
- 調(diào)用setRefreshHeader(IRefreshHeader refreshHeader)即可罗标。
mRecyclerView.setRefreshHeader(new CustomRefreshHeader(this));
示例:
public class CustomRefreshHeader extends BaseRefreshHeader {
private CustomAnimView mCustomAnimView;
public CustomRefreshHeader2(Context context) {
super(context);
}
public CustomRefreshHeader2(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public View getView() {
//方式一
mCustomAnimView = new CustomAnimView(getContext());
return mCustomAnimView;
//方式二
//return LayoutInflater.from(getContext()).inflate(R.layout.clife_loading_header,null);
}
//根據(jù)狀態(tài)改變View
@Override
public void setState(int state) {
super.setState(state);
//選擇自定義需要處理的狀態(tài):STATE_NORMAL、STATE_RELEASE_TO_REFRESH获枝、STATE_REFRESHING蠢正、STATE_DONE
//以下是我自定義動畫需要用到的狀態(tài)判斷,你可以根據(jù)自己需求選擇省店。
if (state == STATE_REFRESHING) { // 顯示進度
//這里處理自己的邏輯嚣崭、刷新中
mCustomAnimView.startAnim();
} else if (state == STATE_DONE) {
//這里處理自己的邏輯、刷新完成
mCustomAnimView.stopAnim();
} else {
mCustomAnimView.startAnim();
}
}
/* @Override
public void refreshComplete() {
//有默認處理懦傍、可以覆蓋該方法處理雹舀,刷新完成的動作
}*/
/*@Override
public void smoothScrollTo(int destHeight) {
//super.smoothScrollTo(destHeight);
//有默認處理、可以覆蓋該方法處理粗俱,順滑改變高度
}*/
//更多方法说榆,可以通過覆寫實現(xiàn),自定義
}
注:如果設置了自定義下拉刷新寸认,setRefreshProgressStyle()會不起作用签财,無需配置,要么采用庫里默認支持的樣式設置废麻,要么采用自定義View荠卷。
自定義加載更多View
- 自定義view實現(xiàn)BaseMoreFooter接口模庐;
- 調(diào)用setLoadingMoreFooter(IMoreFooter refreshHeader)即可烛愧。
mRecyclerView.setLoadingMoreFooter(new CustomMoreFooter(this));
示例:
public class CustomMoreFooter extends BaseMoreFooter {
private AnimationDrawable mAnimationDrawable;
private LinearLayout allLayout;
private TextView mTextView;
public CustomMoreFooter(Context context) {
super(context);
}
public CustomMoreFooter(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void initView() {
super.initView();//有居中顯示功能,如果不需要就去掉super.initView();
allLayout = (LinearLayout) LayoutInflater.from(getContext()).inflate(R.layout.pull_to_refresh_clife, null);
ImageView imageView = (ImageView) allLayout.findViewById(R.id.lodimg);
imageView.setImageResource(R.drawable.icon_loading_animation);
mAnimationDrawable = (AnimationDrawable) imageView.getDrawable();
mTextView = (TextView) allLayout.findViewById(R.id.lodtext);
addView(allLayout);
}
@Override
public void setState(int state) {
super.setState(state);
//以下是我自定義動畫需要用到的狀態(tài)判斷掂碱,你可以根據(jù)自己需求選擇怜姿。
//選擇自定義需要處理的狀態(tài):STATE_LOADING、STATE_COMPLETE疼燥、STATE_NOMORE沧卢、STATE_NOMORE
switch (state) {
case STATE_LOADING:
this.setVisibility(View.VISIBLE);
mAnimationDrawable.start();
mTextView.setText("努力加載中...");
mTextView.setVisibility(VISIBLE);
break;
case STATE_COMPLETE:
this.setVisibility(View.GONE);
mAnimationDrawable.stop();
mTextView.setText("加載完成");
break;
case STATE_NOMORE:
mAnimationDrawable.stop();
mTextView.setText("沒有更多");
this.setVisibility(View.GONE);
break;
}
}
}
注:如果設置了自定義下拉刷新,setRefreshProgressStyle()會不起作用醉者,無需配置但狭,要么采用庫里默認支持的樣式設置,要么采用自定義View撬即。
滑動和加載更多事件監(jiān)聽
mRecyclerView.setLoadingListener(new XRecyclerView.LoadingListener() {
@Override
public void onRefresh() {
//下拉刷新
...
}
@Override
public void onLoadMore() {
//加載更多
...
}
});
設置分割線
分割線可以采用庫中提供的自定義萬能分割線HorizontalDividerItemDecoration和XHorizontalDividerItemDecoration立磁,這里只做使用介紹,詳細請看demo中關于分割線的示例剥槐。
//例1
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this).build());
//例2
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this)
.paint(paint)
.margin(15)
.showLastDivider()
.build());
//例3
recyclerView.addItemDecoration(new com.zhouyou.recyclerview.divider.HorizontalDividerItemDecoration.Builder(this)
//.drawable(R.drawable.divider_sample)//.9圖
.drawable(R.drawable.divider_shape)//shape文件
.size(10)
.build());
//例4
Paint paint = new Paint();
paint.setStrokeWidth(5);
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
paint.setPathEffect(new DashPathEffect(new float[]{15.0f, 15.0f}, 0));
recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this)
.paint(paint)
.margin(15)
.startSkipCount(2)
.endSkipCount(2)
.build());
.....
//更多請看分割線講解
注:此分割線主要是針對LinearLayoutManager使用,對GridLayoutManager和StaggeredGridAdapter支持性比較差唱歧,針對這一類的分割線還需要自定義實現(xiàn)。
設置側滑菜單
設置側滑菜單需要用到自定義SwipeMenuRecyclerView,此view是繼承自XRecyclerView颅崩,具備XRecyclerView的所有功能和屬性几于。
1.Xml布局引用SwipeMenuRecyclerView
<com.zhouyou.recyclerview.swipemenu.SwipeMenuRecyclerView
android:id="@+id/super_swipemenu_recycle_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
2.側滑菜單對適配器沒有特殊要求可以繼承任意Adapter,但是對item的布局文件有要求沿后,需要用SwipeMenuLayout沿彭。
例如:adapter_menu_layout_item.xml
<?xml version="1.0" encoding="utf-8"?>
<!--布局外層必須用SwipeMenuLayout-->
<com.zhouyou.recyclerview.swipemenu.SwipeMenuLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--內(nèi)容布局id必須用smContentView,不能自定義id名稱尖滚,否則找不到-->
<include
android:id="@+id/smContentView"
layout="@layout/item_swipe_menu_content" />
<!--菜單布局id必須用smMenuView膝蜈,不能自定義id名稱,否則找不到-->
<include
android:id="@+id/smMenuView"
layout="@layout/item_swipe_menu1" />
</com.zhouyou.recyclerview.swipemenu.SwipeMenuLayout>
注:其它關于SwipeMenuLayout更多使用方法熔掺,請參考demo示例饱搏。
設置sticky懸停
主要提供了兩種懸停效果:一種是鴻洋大神的StickyNavLayout,另一種是用StickyNestedScrollView(繼承自V4包NestedScrollView進行擴展)置逻。為什么會把這兩種懸停效果放到庫中處理呢推沸,因為XRecyclerView、StickyNavLayout/StickyNestedScrollView券坞、Tablayout鬓催、ViewPager、HelperRecyclerViewAdapter等相互組合使用會存在沖突等問題恨锚,本庫中都已經(jīng)解決了存在的已知兼容問題宇驾,互相打通,另一方面也是收集常用功能對EasyXRecyclerView的完善猴伶。
StickyNavLayout使用介紹:
可以設置頁面某個控件滑動懸停课舍,底部內(nèi)容區(qū)域支持 ScrollView ,ListView,RecyclerView他挎。
注意控件id的設置
- top區(qū)域:id必須為 android:id="@+id/id_stickynavlayout_topview"
- 懸浮區(qū)域:id必須為android:id="@+id/id_stickynavlayout_indicator"
- 內(nèi)容區(qū)域:id必須為android:id="@+id/id_stickynavlayout_viewpager"
內(nèi)容區(qū)域
- 此方式內(nèi)容區(qū)域必須需為ViewPager或者其子類
- ViewPager的內(nèi)容可以是Fragment,如果Fragment里面是ListView,RecycleView等需要設置其id為:android:id="@+id/id_stickynavlayout_innerscrollview"
在xml中引入:
<?xml version="1.0" encoding="utf-8"?>
<com.zhouyou.recyclerview.sticky.StickyNavLayout
android:id="@+id/id_stick"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
app:isStickNav="false">
<!--頭部布局 id必須設置為:id_stickynavlayout_topview-->
<LinearLayout
android:id="@id/id_stickynavlayout_topview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--寫頭部區(qū)域內(nèi)容-->
...
</LinearLayout>
<!--需要懸停內(nèi)容的布局 id必須設置為:id_stickynavlayout_indicator-->
<LinearLayout
android:id="@id/id_stickynavlayout_indicator"
...
>
<!--寫懸停部區(qū)域內(nèi)容-->
...
</LinearLayout>
<!--底部內(nèi)容區(qū)域布局筝尾,ViewPager id必須設置為:id_stickynavlayout_viewpager-->
<!--如果Viewpager里面裝載的內(nèi)容為ListView,RecycleView、XRecycleView等需要設置其id為id_stickynavlayout_innerscrollview-->
<android.support.v4.view.ViewPager
android:id="@id/id_stickynavlayout_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</com.zhouyou.recyclerview.sticky.StickyNavLayout>
注:更多使用功能請參考鴻洋大神的講解办桨。
StickyNestedScrollView使用介紹:
StickyNestedScrollView方式使用比較簡單筹淫,可以支持設置多個懸停。只需要在需要懸停的控件上設置tag屬性呢撞,tag屬性可以設置為:sticky损姜、sticky-nonconstant、sticky-hastransparency殊霞,一般直接使用android:tag="sticky"
摧阅。
在xml中引入:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<com.zhouyou.recyclerview.sticky.StickyNestedScrollView
android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!--只要將需要懸停的控件設置tag為:sticky就可以懸停-->
<TextView
...
android:tag="sticky"
android:text="A"/>
<!--B沒有設置tag就不會懸停-->
<TextView
...
android:text="B"/>
<!--C設置tag就會和A一樣可以懸停-->
<TextView
...
android:tag="sticky"
android:text="B"/>
</LinearLayout>
</com.zhouyou.recyclerview.sticky.StickyNestedScrollView>
</android.support.design.widget.CoordinatorLayout>
StickyNestedScrollView支持的方法addOnViewStickyListener(OnViewStickyListener stickyListener)、removeOnViewStickyListener(OnViewStickyListener stickyListener)脓鹃、clearOnViewStickyListener()逸尖、setShadowHeight(int height)、setShadowDrawable(Drawable shadowDrawable)
。如果XRecyclerview適配器中的某個item需要懸停娇跟,只需要將item布局設置android:tag="sticky"
即可實現(xiàn)item懸停岩齿,但是這樣會有一個問題,如果在xml中靜態(tài)設置所有的item都會有懸停苞俘,可以在設配器中獲取到item布局對象根據(jù)業(yè)務邏輯進行動態(tài)設置view.setTag("sticky");
StickyNavLayout與StickyNestedScrollView對比
- StickyNavLayout使用起來相對于StickyNestedScrollView比較麻煩盹沈,特別是要注意Id的設置,StickyNestedScrollView使用更加便捷一些吃谣。
- StickyNavLayout支持單個懸停乞封,StickyNestedScrollView支持多個懸停。
- StickyNestedScrollView不適合與帶有刷新和加載更多的Recyclerview嵌套岗憋,嵌套后Recyclerview的加載更多會失效肃晚,而StickyNavLayout不會影響加載跟多功能。
- 如果內(nèi)容比較多建議采用StickyNavLayout+Recyclerview來實現(xiàn)分頁帶有頭部的列表懸停功能仔戈,StickyNestedScrollView+Recyclerview不能裝載太多的數(shù)據(jù)特別是用于分頁关串。因為StickyNestedScrollView原理是把Recyclerview的滑動事件都轉移給自己來處理,這樣Recyclerview的復用機制就會不起作用监徘,數(shù)據(jù)過多容易OOM.單頁面且數(shù)據(jù)量不多可以采用StickyNestedScrollView更簡單晋修。
注:其它更多復雜的懸停使用場景請參考demo中關于Sticky部分的示例。
完整示例
所有的屬性設置凰盔,都是根據(jù)自己的需要進行設置墓卦,不需要把所有屬性都設置一遍,切記户敬!切記落剪!切記!
XRecyclerView mRecyclerView = (com.zhouyou.recyclerview.XRecyclerView) this.findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setAutoMeasureEnabled(true);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
//刷新方式二選一:方式一or方式二
//方式一:采用庫中提供的默認刷新樣式
mRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader); //設置下拉刷新Progress的樣式,在ProgressStyle里面選擇喜歡的樣式
mRecyclerView.setArrowImageView(R.drawable.iconfont_downgrey);//設置下拉刷新箭頭
mRecyclerView.setLoadingMoreProgressStyle(ProgressStyle.BallPulse); //設置加載更多Progress的樣式
mRecyclerView.setFootViewText("拼命加載中","已經(jīng)全部");
//方式二:完全采用自定義的刷新動畫
//mRecyclerView.setRefreshHeader(new CustomRefreshHeader(this));
//mRecyclerView.setLoadingMoreFooter(new CustomLoadingMoreFooter(this));
//打開刷新和加載更多
//mRecyclerView.setPullRefreshEnabled(true);
//mRecyclerView.setLoadingMoreEnabled(true);
//添加一個頭部view和尾部view
View headerView = LayoutInflater.from(this).inflate(R.layout.layout_header, (ViewGroup)findViewById(android.R.id.content),false);
View footerView = getLayoutInflater().inflate(R.layout.layout_footer, (ViewGroup) mRecyclerView.getParent(), false);
mRecyclerView.addHeaderView(headerView);
mRecyclerView.addFooterView(footerView);
//分割線設置
mRecyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(this).build());
//移除添加的頭部view
mRecyclerView.removeHeaderView(headerView);
//移除添加的尾部view
mRecyclerView.removeFooterView(footerView);
mRecyclerView.setLoadingListener(new XRecyclerView.LoadingListener() {
@Override
public void onRefresh() {
//下拉刷新
//mRecyclerView.refreshComplete();//刷新動畫完成
}
@Override
public void onLoadMore() {
//加載更多
//mRecyclerView.loadMoreComplete();//加載動畫完成
//mRecyclerView.setNoMore(true);//數(shù)據(jù)加載完成
}
});
//裝載數(shù)據(jù)
MyAdapter mAdapter = new MyAdapter(this);
mRecyclerView.setAdapter(mAdapter);//本庫不成文規(guī)定山叮,最好使用setAdapter寫在裝載數(shù)據(jù)之前
mAdapter.setListAll(datas);//該動作放在setAdapter之后