給listview和recyclerview添加header和footer,我們一般常用的方式,有如下幾種:
xml文件:
1.自定義listview和recyclerview.添加頭和尾
2.使用第三方框架PullToRefresh進(jìn)行添加頭和尾
3.使用谷歌最新推出的控件SwipeRefreshLayout,下面我們就來講解一下怎么使用谷歌最新的特性進(jìn)行添加頭和尾
該控件有一個(gè)缺點(diǎn):自帶功能中沒有添加叫布局加載更多的方法.
上圖:
只需要添加下拉加載更多的話,直接使用原生的控件即可:
上代碼:
privateListViewlv;
privateArrayListlist=newArrayList<>();
privateListviewAdaptermAdapter;
privateSwipeRefreshLayoutswipe;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
lv= (ListView) findViewById(R.id.lv_listview);
swipe= (SwipeRefreshLayout) findViewById(R.id.swipe);
init();
//設(shè)置下拉刷新的顏色
swipe.setProgressBackgroundColorSchemeResource(android.R.color.holo_red_light);
//下拉時(shí)觸發(fā)SwipeRefreshLayout的下拉動(dòng)畫檩奠,動(dòng)畫完畢之后就會(huì)回調(diào)這個(gè)方法
swipe.setOnRefreshListener(newSwipeRefreshLayout.OnRefreshListener() {
@Override
public voidonRefresh() {
//開始刷新酵幕,設(shè)置當(dāng)前為刷新狀態(tài)
//swipeRefreshLayout.setRefreshing(true);
//這里是主線程
//一些比較耗時(shí)的操作,比如聯(lián)網(wǎng)獲取數(shù)據(jù)菠镇,需要放到子線程去執(zhí)行
//TODO獲取數(shù)據(jù)
finalRandom random =newRandom();
newHandler().postDelayed(newRunnable() {
@Override
public voidrun() {
list.add(0,"我是刷新天才"+random.nextInt(100) +"號(hào)");
mAdapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this,"刷新了一條數(shù)據(jù)", Toast.LENGTH_SHORT).show();
//加載完數(shù)據(jù)設(shè)置為不刷新狀態(tài)昂秃,將下拉進(jìn)度收起來
swipe.setRefreshing(false);
}
},2000);
}
});
}
/**
*@authorhy
@time2016/10/1 17:57
/
private voidinit() {
addData();
if(list!=null) {
if(mAdapter==null) {
mAdapter=newListviewAdapter(this,list);
lv.setAdapter(mAdapter);
}else{
mAdapter.notifyDataSetChanged();
}
}
}
/
*@authorhy
@time2016/10/1 17:57
/
public voidaddData() {
for(inti =1; i <=100; i++) {
list.add("我是天才"+ i +"號(hào)");
}
}
xml布局文件:
就是一個(gè)swipeRefreshLayout里面包裹一個(gè)listview即可.
添加footer,上啦加載更多,自定義該控件.
/
*作者:hy on 2016/10/2 00:02
郵箱: simoncqhy@163.com
/
public classSwipeRefreshViewextendsSwipeRefreshLayout {
privateViewmFooterView;
//滑動(dòng)的最小距離
private intmSlop;
//獲取listview
privateListViewmListView;
privateOnLoadListenermOnLoadListener;
//正在加載狀態(tài)
private booleanisLoading;
publicSwipeRefreshView(Context context) {
this(context,null);
}
publicSwipeRefreshView(Context context, AttributeSet attrs) {
super(context, attrs);
mFooterView= View.inflate(context, R.layout.view_footer,null);
//設(shè)置滑動(dòng)的最小距離,大于該距離才能滑動(dòng)禀梳。
mSlop= ViewConfiguration.get(context).getScaledTouchSlop();
}
@Override
protected voidonLayout(booleanchanged,intleft,inttop,intright,intbottom) {
super.onLayout(changed, left, top, right, bottom);
if(mListView==null) {
//判斷容器有多少個(gè)子孩子
if(getChildCount()>0) {
//判斷第一個(gè)孩子是不是ListView
if(getChildAt(0)instanceofListView) {
//創(chuàng)建ListView對(duì)象
mListView= (ListView) getChildAt(0);
//設(shè)置ListView的滑動(dòng)監(jiān)聽
setListViewOnScroll();
}
}
}
}
//設(shè)置listview的滑動(dòng)監(jiān)聽
private voidsetListViewOnScroll() {
mListView.setOnScrollListener(newAbsListView.OnScrollListener() {
@Override
public voidonScrollStateChanged(AbsListView view,intscrollState) {
//移動(dòng)過程中判斷時(shí)候能下拉加載更多
if(canLoadMore()) {
//加載數(shù)據(jù)
loadData();
}
}
@Override
public voidonScroll(AbsListView view,intfirstVisibleItem,intvisibleItemCount,inttotalItemCount) {
}
});
}
/
*分發(fā)事件的處理
*@paramev
@return
/
private floatmDownY,mUpY;
@Override
public booleandispatchTouchEvent(MotionEvent ev) {
switch(ev.getAction()) {
caseMotionEvent.ACTION_DOWN:
//移動(dòng)的起點(diǎn)
mDownY= ev.getY();
break;
caseMotionEvent.ACTION_MOVE:
//移動(dòng)過程中判斷時(shí)候能下拉加載更多
if(canLoadMore()) {
//加載數(shù)據(jù)
loadData();
}
break;
caseMotionEvent.ACTION_UP:
//移動(dòng)的終點(diǎn)
mUpY= getY();
break;
}
return super.dispatchTouchEvent(ev);
}
/
*判斷是否能夠加載更多
@return
/
private booleancanLoadMore() {
// 1.是上拉狀態(tài)
booleancondition1 = (mDownY-mUpY) >=mSlop;
if(condition1) {
System.out.println("是上拉狀態(tài)");
}
// 2.當(dāng)前頁面可見的item是最后一個(gè)條目
booleancondition2 =false;
if(mListView!=null&&mListView.getAdapter() !=null) {
condition2 =mListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() -1);
}
if(condition2) {
System.out.println("是最后一個(gè)條目");
}
// 3.正在加載狀態(tài)
booleancondition3 = !isLoading;
if(condition3) {
System.out.println("不是正在加載狀態(tài)");
}
returncondition1 && condition2 && condition3;
}
/
處理加載數(shù)據(jù)的邏輯
/
private voidloadData() {
System.out.println("加載數(shù)據(jù)...");
if(mOnLoadListener!=null) {
//設(shè)置加載狀態(tài)杜窄,讓布局顯示出來
setLoading(true);
mOnLoadListener.onLoad();
}
}
/
*設(shè)置加載狀態(tài),是否加載傳入boolean值進(jìn)行判斷
@paramloading
/
public voidsetLoading(booleanloading) {
//修改當(dāng)前的狀態(tài)
isLoading= loading;
if(isLoading) {
//顯示布局
mListView.addFooterView(mFooterView);
}else{
//隱藏布局
mListView.removeFooterView(mFooterView);
//重置滑動(dòng)的坐標(biāo)
mDownY=0;
mUpY=0;
}
}
/
上拉加載的接口回調(diào)
/
public interfaceOnLoadListener {
voidonLoad();
}
public voidsetOnLoadListener(OnLoadListener listener) {
this.mOnLoadListener= listener;
}
}
使用:
/
*作者:hy on 2016/10/2 00:16
郵箱: simoncqhy@163.com
/
public classCustomActivityextendsAppCompatActivity {
privateListmList;
private intmCount;
privateStringAdaptermAdapter;
@Override
protected voidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom);
finalSwipeRefreshView swipeRefreshView = (SwipeRefreshView) findViewById(R.id.srl);
finalListView listView = (ListView) findViewById(R.id.lv);
//設(shè)置適配器數(shù)據(jù)
mList=newArrayList<>();
for(inti =0; i <30; i++) {
mList.add("我是天才"+ i +"號(hào)");
mCount++;
}
mAdapter=newStringAdapter();
listView.setAdapter(mAdapter);
//不能在onCreate中設(shè)置算途,這個(gè)表示當(dāng)前是刷新狀態(tài)塞耕,如果一進(jìn)來就是刷新狀態(tài),SwipeRefreshLayout會(huì)屏蔽掉下拉事件
//swipeRefreshLayout.setRefreshing(true);
//設(shè)置顏色屬性的時(shí)候一定要注意是引用了資源文件還是直接設(shè)置16進(jìn)制的顏色嘴瓤,因?yàn)槎际莍nt值容易搞混
//設(shè)置下拉進(jìn)度的背景顏色扫外,默認(rèn)就是白色的
swipeRefreshView.setProgressBackgroundColorSchemeResource(android.R.color.white);
//設(shè)置下拉進(jìn)度的主題顏色
swipeRefreshView.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary, R.color.colorPrimaryDark);
//下拉時(shí)觸發(fā)SwipeRefreshLayout的下拉動(dòng)畫,動(dòng)畫完畢之后就會(huì)回調(diào)這個(gè)方法
swipeRefreshView.setOnRefreshListener(newSwipeRefreshLayout.OnRefreshListener() {
@Override
public voidonRefresh() {
//開始刷新廓脆,設(shè)置當(dāng)前為刷新狀態(tài)
//swipeRefreshLayout.setRefreshing(true);
//這里是主線程
//一些比較耗時(shí)的操作筛谚,比如聯(lián)網(wǎng)獲取數(shù)據(jù),需要放到子線程去執(zhí)行
//TODO獲取數(shù)據(jù)
finalRandom random =newRandom();
newHandler().postDelayed(newRunnable() {
@Override
public voidrun() {
mList.add(0,"我是下拉天才"+random.nextInt(100) +"號(hào)");
mAdapter.notifyDataSetChanged();
Toast.makeText(CustomActivity.this,"刷新了一條數(shù)據(jù)", Toast.LENGTH_SHORT).show();
//加載完數(shù)據(jù)設(shè)置為不刷新狀態(tài)停忿,將下拉進(jìn)度收起來
swipeRefreshView.setRefreshing(false);
}
},2000);
}
});
//設(shè)置下拉加載更多
swipeRefreshView.setOnLoadListener(newSwipeRefreshView.OnLoadListener() {
@Override
public voidonLoad() {
newHandler().postDelayed(newRunnable() {
@Override
public voidrun() {
//添加數(shù)據(jù)
for(inti =30; i <35; i++) {
mList.add("我是加載更多天才"+ i+"號(hào)");
//這里要放在里面刷新驾讲,放在外面會(huì)導(dǎo)致刷新的進(jìn)度條卡住
mAdapter.notifyDataSetChanged();
}
Toast.makeText(CustomActivity.this,"加載了"+5+"條數(shù)據(jù)", Toast.LENGTH_SHORT).show();
//加載完數(shù)據(jù)設(shè)置為不加載狀態(tài),將加載進(jìn)度收起來
swipeRefreshView.setLoading(false);
}
},2000);
}
});
}
/
*適配器
*/
private classStringAdapterextendsBaseAdapter {
@Override
public intgetCount() {
returnmList.size();
}
@Override
publicObject getItem(intposition) {
returnmList.get(position);
}
@Override
public longgetItemId(intposition) {
returnposition;
}
@Override
publicView getView(intposition, View convertView, ViewGroup parent) {
if(convertView ==null) {
convertView = View.inflate(CustomActivity.this, android.R.layout.simple_list_item_1,null);
}
TextView tv = (TextView) convertView;
tv.setGravity(Gravity.CENTER);
tv.setPadding(0,20,0,20);
tv.setText(mList.get(position));
returnconvertView;
}
}
}
源碼下載地址
百度云盤:
http://pan.baidu.com/s/1eRU3mpG