给listview和recyclerview添加header和footer,我们一般常用的方式,有如下几种:
xml文件:
1.自定义listview和recyclerview.添加头和尾
2.使用第三方框架PullToRefresh进行添加头和尾
3.使用谷歌最新推出的控件SwipeRefreshLayout,下面我们就来讲解一下怎么使用谷歌最新的特性进行添加头和尾
该控件有一个缺点:自带功能中没有添加叫布局加载更多的方法.
上图:
只需要添加下拉加载更多的话,直接使用原生的控件即可:
上代码:
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();
//设置下拉刷新的颜色
swipe.setProgressBackgroundColorSchemeResource(android.R.color.holo_red_light);
//下拉时触发SwipeRefreshLayout的下拉动画,动画完毕之后就会回调这个方法
swipe.setOnRefreshListener(newSwipeRefreshLayout.OnRefreshListener() {
@Override
public voidonRefresh() {
//开始刷新,设置当前为刷新状态
//swipeRefreshLayout.setRefreshing(true);
//这里是主线程
//一些比较耗时的操作,比如联网获取数据,需要放到子线程去执行
//TODO获取数据
finalRandom random =newRandom();
newHandler().postDelayed(newRunnable() {
@Override
public voidrun() {
list.add(0,"我是刷新天才"+random.nextInt(100) +"号");
mAdapter.notifyDataSetChanged();
Toast.makeText(MainActivity.this,"刷新了一条数据", Toast.LENGTH_SHORT).show();
//加载完数据设置为不刷新状态,将下拉进度收起来
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 +"号");
}
}
xml布局文件:
就是一个swipeRefreshLayout里面包裹一个listview即可.
添加footer,上啦加载更多,自定义该控件.
/
*作者:hy on 2016/10/2 00:02
邮箱: simoncqhy@163.com
/
public classSwipeRefreshViewextendsSwipeRefreshLayout {
privateViewmFooterView;
//滑动的最小距离
private intmSlop;
//获取listview
privateListViewmListView;
privateOnLoadListenermOnLoadListener;
//正在加载状态
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);
//设置滑动的最小距离,大于该距离才能滑动。
mSlop= ViewConfiguration.get(context).getScaledTouchSlop();
}
@Override
protected voidonLayout(booleanchanged,intleft,inttop,intright,intbottom) {
super.onLayout(changed, left, top, right, bottom);
if(mListView==null) {
//判断容器有多少个子孩子
if(getChildCount()>0) {
//判断第一个孩子是不是ListView
if(getChildAt(0)instanceofListView) {
//创建ListView对象
mListView= (ListView) getChildAt(0);
//设置ListView的滑动监听
setListViewOnScroll();
}
}
}
}
//设置listview的滑动监听
private voidsetListViewOnScroll() {
mListView.setOnScrollListener(newAbsListView.OnScrollListener() {
@Override
public voidonScrollStateChanged(AbsListView view,intscrollState) {
//移动过程中判断时候能下拉加载更多
if(canLoadMore()) {
//加载数据
loadData();
}
}
@Override
public voidonScroll(AbsListView view,intfirstVisibleItem,intvisibleItemCount,inttotalItemCount) {
}
});
}
/
*分发事件的处理
*@paramev
@return
/
private floatmDownY,mUpY;
@Override
public booleandispatchTouchEvent(MotionEvent ev) {
switch(ev.getAction()) {
caseMotionEvent.ACTION_DOWN:
//移动的起点
mDownY= ev.getY();
break;
caseMotionEvent.ACTION_MOVE:
//移动过程中判断时候能下拉加载更多
if(canLoadMore()) {
//加载数据
loadData();
}
break;
caseMotionEvent.ACTION_UP:
//移动的终点
mUpY= getY();
break;
}
return super.dispatchTouchEvent(ev);
}
/
*判断是否能够加载更多
@return
/
private booleancanLoadMore() {
// 1.是上拉状态
booleancondition1 = (mDownY-mUpY) >=mSlop;
if(condition1) {
System.out.println("是上拉状态");
}
// 2.当前页面可见的item是最后一个条目
booleancondition2 =false;
if(mListView!=null&&mListView.getAdapter() !=null) {
condition2 =mListView.getLastVisiblePosition() == (mListView.getAdapter().getCount() -1);
}
if(condition2) {
System.out.println("是最后一个条目");
}
// 3.正在加载状态
booleancondition3 = !isLoading;
if(condition3) {
System.out.println("不是正在加载状态");
}
returncondition1 && condition2 && condition3;
}
/
处理加载数据的逻辑
/
private voidloadData() {
System.out.println("加载数据...");
if(mOnLoadListener!=null) {
//设置加载状态,让布局显示出来
setLoading(true);
mOnLoadListener.onLoad();
}
}
/
*设置加载状态,是否加载传入boolean值进行判断
@paramloading
/
public voidsetLoading(booleanloading) {
//修改当前的状态
isLoading= loading;
if(isLoading) {
//显示布局
mListView.addFooterView(mFooterView);
}else{
//隐藏布局
mListView.removeFooterView(mFooterView);
//重置滑动的坐标
mDownY=0;
mUpY=0;
}
}
/
上拉加载的接口回调
/
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);
//设置适配器数据
mList=newArrayList<>();
for(inti =0; i <30; i++) {
mList.add("我是天才"+ i +"号");
mCount++;
}
mAdapter=newStringAdapter();
listView.setAdapter(mAdapter);
//不能在onCreate中设置,这个表示当前是刷新状态,如果一进来就是刷新状态,SwipeRefreshLayout会屏蔽掉下拉事件
//swipeRefreshLayout.setRefreshing(true);
//设置颜色属性的时候一定要注意是引用了资源文件还是直接设置16进制的颜色,因为都是int值容易搞混
//设置下拉进度的背景颜色,默认就是白色的
swipeRefreshView.setProgressBackgroundColorSchemeResource(android.R.color.white);
//设置下拉进度的主题颜色
swipeRefreshView.setColorSchemeResources(R.color.colorAccent, R.color.colorPrimary, R.color.colorPrimaryDark);
//下拉时触发SwipeRefreshLayout的下拉动画,动画完毕之后就会回调这个方法
swipeRefreshView.setOnRefreshListener(newSwipeRefreshLayout.OnRefreshListener() {
@Override
public voidonRefresh() {
//开始刷新,设置当前为刷新状态
//swipeRefreshLayout.setRefreshing(true);
//这里是主线程
//一些比较耗时的操作,比如联网获取数据,需要放到子线程去执行
//TODO获取数据
finalRandom random =newRandom();
newHandler().postDelayed(newRunnable() {
@Override
public voidrun() {
mList.add(0,"我是下拉天才"+random.nextInt(100) +"号");
mAdapter.notifyDataSetChanged();
Toast.makeText(CustomActivity.this,"刷新了一条数据", Toast.LENGTH_SHORT).show();
//加载完数据设置为不刷新状态,将下拉进度收起来
swipeRefreshView.setRefreshing(false);
}
},2000);
}
});
//设置下拉加载更多
swipeRefreshView.setOnLoadListener(newSwipeRefreshView.OnLoadListener() {
@Override
public voidonLoad() {
newHandler().postDelayed(newRunnable() {
@Override
public voidrun() {
//添加数据
for(inti =30; i <35; i++) {
mList.add("我是加载更多天才"+ i+"号");
//这里要放在里面刷新,放在外面会导致刷新的进度条卡住
mAdapter.notifyDataSetChanged();
}
Toast.makeText(CustomActivity.this,"加载了"+5+"条数据", Toast.LENGTH_SHORT).show();
//加载完数据设置为不加载状态,将加载进度收起来
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