ListView实现下拉刷新三实现下拉刷新.docx
《ListView实现下拉刷新三实现下拉刷新.docx》由会员分享,可在线阅读,更多相关《ListView实现下拉刷新三实现下拉刷新.docx(15页珍藏版)》请在冰豆网上搜索。
ListView实现下拉刷新三实现下拉刷新
实现下拉刷新
该准备的东西都已经准备好了。
在这篇文章里,我们就开始实现下拉刷新功能吧。
一、大体的逻辑分析
我们来简单分析一下需要做的逻辑吧。
首先分析头布局有几种状态。
不下拉时,为正常状态,此时头布局隐藏。
下拉到一定高度,提示信息变为“下拉刷新”,箭头朝下,此为下拉状态。
再往下拉,提示信息变为“松开刷新”,箭头朝上,此为提示刷新状态。
而此时松开手指,则执行刷新操作,头布局变为进度条显示,箭头消失,此为正在刷新状态。
相反的,其他状态下松开手指,都不执行刷新操作,应该将头布局恢复到正常状态。
因为可确定头布局的状态有四种。
我们根据这四种状态,确定我们要做的事情。
要监听ListView的滚动,故要实现OnScrollListener接口。
还要监听手指触摸事件,根据手指的下拉移动来改变头布局的显示效果,根据手指的抬起来判断是否进行刷新操作,因为要实现onTouchEvent方法。
也就是说,头布局状态的改变应该随着手指的移动而改变,因此在onTouchEvent里面我们要实现上面分析的四种状态的改变。
当然,状态改变就意味着头布局显示效果的改变,这里可以嵌套在onTouchEvent方法里面。
但考虑到避免方法臃肿,以及其他地方可能也需要改变头布局界面,比如数据加载完成后等情况,因此专门将头布局界面的改变抽取出来,凝聚为一个方法。
然后就是数据刷新,刷新操作要在MyListView里执行,但是数据要在MainActivity中获取。
老规矩,用接口回调即可。
好了,基本上大体的逻辑就这么多了。
下面我们将上面的分析转化为代码。
二、代码编写
废话我就不多说了,上面的分析很清楚了。
继续完善MyListView即可。
代码如下:
packagecom.fuly.load;
importandroid.content.Context;
importandroid.util.AttributeSet;
importandroid.view.LayoutInflater;
importandroid.view.MotionEvent;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.widget.AbsListView;
importandroid.widget.AbsListView.OnScrollListener;
importandroid.widget.ImageView;
importandroid.widget.ListView;
importandroid.widget.ProgressBar;
importandroid.widget.TextView;
publicclassMyListViewextendsListViewimplementsOnScrollListener{
privateViewheader;//头布局
privateintheaderHeight;//头布局自身的高度
privateintscrollState;//当前滚动状态
privateintfirstVisibleItem;//当前可见的第一个item
privateintstartY;//刚开始触摸屏幕时的Y值
privateintcurState=0;//当前header状态,默认为0
privatefinalintNORMAL=0;//正常状态
privatefinalintPULL=1;//状态下拉
privatefinalintRELEASE=2;//提示刷新状态
privatefinalintRELEASING=3;//状态正在刷新
privatebooleancanPull=false;//是否可以执行下拉操作
privaterefresfListenermListener;//回调接口
//三个构造方法都要重写
publicMyListView(Contextcontext){
super(context);
initView(context);
}
publicMyListView(Contextcontext,AttributeSetattrs){
super(context,attrs);
initView(context);
}
publicMyListView(Contextcontext,AttributeSetattrs,intdefStyle){
super(context,attrs,defStyle);
initView(context);
}
//定义回调接口
publicinterfacerefresfListener{
voidrefresh();
}
publicvoidsetOnRefreshListener(refresfListenerlistener){
this.mListener=listener;
}
publicvoidinitView(Contextcontext){
header=LayoutInflater.from(context).inflate(R.layout.header,null);
notifyView(header);
headerHeight=header.getMeasuredHeight();//获取header的高度
//headerHeight=header.getHeight();
paddingTop(-headerHeight);
//将头布局加进去
this.addHeaderView(header);
this.setOnScrollListener(this);
}
/**
*该方法为通知父布局,子布局view的宽度和高度
*@paramview:
子布局
*/
privatevoidnotifyView(Viewview){
ViewGroup.LayoutParamsp=view.getLayoutParams();
if(p==null){
p=newViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
}
//spec表示当前子view左右边距,padding表示子view的左右内边距
//childDimension:
子view的宽度
intwidth=ViewGroup.getChildMeasureSpec(0,0,p.width);
intheight;
inttempHeight=p.height;
if(tempHeight>0){
//子布局高度不为空,需要填充这个布局
height=MeasureSpec.makeMeasureSpec(tempHeight,MeasureSpec.EXACTLY);
}else{
//高度为0,则不需要填充
height=MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);
}
//然后告诉父布局,子布局的高度和宽度
view.measure(width,height);
}
//该方法设定header的paddingTop
privatevoidpaddingTop(intpt){
header.setPadding(header.getPaddingLeft(),pt,header.getPaddingRight(),header.getPaddingBottom());
header.invalidate();
}
/***
*监听当前滚动状态
*scrollState:
当前滚动状态
*/
publicvoidonScrollStateChanged(AbsListViewview,intscrollState){
//记录当前的滚动状态
this.scrollState=scrollState;
}
/***
*监听当前滚动的item
*firstVisibleItem:
当前可见的第一个item
*visibleItemCount:
当前共有多少个item可见
*totalItemCount:
总共有多少个item
*
*/
publicvoidonScroll(AbsListViewview,intfirstVisibleItem,
intvisibleItemCount,inttotalItemCount){
this.firstVisibleItem=firstVisibleItem;
}
//触屏事件
publicbooleanonTouchEvent(MotionEventev){
switch(ev.getAction()){
//手指落到屏幕上时
caseMotionEvent.ACTION_DOWN:
//如果当前可见的第一个item为第0号,说明ListView位于顶端,可以执行下拉刷新
if(firstVisibleItem==0){
canPull=true;
startY=(int)ev.getY();
}
break;
//手指在屏幕上拖动时
caseMotionEvent.ACTION_MOVE:
if(canPull){
touchMove(ev);
}
break;
//手指离开屏幕时
caseMotionEvent.ACTION_UP:
canPull=false;
if(curState==RELEASE){
curState=RELEASING;
refreshHeaderByState();
//这里添加刷新数据的逻辑
mListener.refresh();
}else{
curState=NORMAL;
refreshHeaderByState();
paddingTop(-headerHeight);
}
break;
}
returnsuper.onTouchEvent(ev);
}
/**
*该方法根据触摸屏幕滑动来改变STATE,即改变当前状态
*@paramev
*/
privatevoidtouchMove(MotionEventev){
inttempY=(int)ev.getY();
intspace=tempY-startY;//移动的距离
inttopdding=space-headerHeight;
paddingTop(topdding);//即时设定头布局的隐藏高度
if(space>headerHeight&&spacecurState=PULL;//设定为下拉状态
refreshHeaderByState();
}
if(space>headerHeight+50){
curState=RELEASE;//设定为提示刷新状态
refreshHeaderByState();
}
if(spacecurState=NORMAL;//设定为正常状态
refreshHeaderByState();
}
}
/**
*根据当前状态更改header的显示界面
*
*/
privatevoidrefreshHeaderByState(){
ProgressBarpb=(ProgressBar)header.findViewById(R.id.progress_bar);
ImageViewimg=(ImageView)header.findViewById(R.id.img_arrow);
TextViewtv=(TextView)header.findViewById(R.id.textinfo);
switch(curState){
caseNORMAL:
pb.setVisibility(View.GONE);
img.setVisibility(View.VISIBLE);
img.setImageResource(R.drawable.down_arrow);
tv.setText("下拉刷新");
break;
casePULL:
pb.setVisibility(View.GONE);
img.setVisibility(View.VISIBLE);
img.setImageResource(R.drawable.down_arrow);
tv.setText("下拉刷新");
break;
caseRELEASE:
pb.setVisibility(View.GONE);
img.setVisibility(View.VISIBLE);
img.setImageResource(R.drawable.up_arrow);
tv.setText("松开刷新");
break;
caseRELEASING:
pb.setVisibility(View.VISIBLE);
img.setVisibility(View.GONE);
tv.setText("正在刷新");
break;
}
}
//数据刷新完成后的操作
publicvoidrefreshFinish(){
curState=NORMAL;
paddingTop(-headerHeight);
refreshHeaderByState();
}
}
接下来就是MainActivity中的代码了。
如下:
packagecom.fuly.load;
importjava.util.ArrayList;
importjava.util.List;
importcom.fuly.load.MyListView.refresfListener;
importandroid.os.Bundle;
importandroid.os.Handler;
importandroid.app.Activity;
publicclassMainActivityextendsActivityimplementsrefresfListener{
privateMyListViewlv;
privateListmDatas=newArrayList();
privateMyAdaptermAdapter;
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();//该方法初始化数据
lv=(MyListView)findViewById(R.id.list_view);
lv.setOnRefreshListener(this);//设定回调接口
mAdapter=newMyAdapter(this,mDatas);
lv.setAdapter(mAdapter);
}
/**
*该方法初始化数据,即提供初始的素材
*/
privatevoidinitData(){
for(inti=0;i<12;i++){
MyDatamd=newMyData("你好,我是提前设定的");
mDatas.add(md);
}
}
/**
*提供刷新数据
*/
privatevoidgetRefreshData(){
for(inti=0;i<3;i++){
MyDatamd=newMyData("你好,我是刷新进来的");
mDatas.add(i,md);
}
}
//重写回调方法
publicvoidrefresh(){
//在这里之所以使用Handler,是想让操作延迟,这样子效果看起来更
//清晰,实际项目中,是不需要的
HandlermHandler=newHandler();
mHandler.postDelayed(newRunnable(){
@Override
publicvoidrun(){
//获得刷新数据
getRefreshData();
//刷新ListView
mAdapter.notifyDataSetChanged();
//lv.setSelection(mDatas.size()-1);
//刷新后
lv.refreshFinish();
}
},5000);
}
}
好了,快快运行下程序,体验下拉刷新的效果吧。
至此,ListView实现下拉刷新,我们讲解完毕了。