在android中有时我们要实现下拉刷新的功能,我在前日人的基础上自己实现了一个。
其实实现的原理很简单,显示在listView的headerView中添加一个要刷新的进度条显示设置这个view影藏,在你拖动listView的时候当你托到最上面的时候,进行判断显示,影藏进度条,在显示进度条后你松开手势的时候根据不同的状态实现页面的操作。不多说了,实现的代码如下:
显示声明一个显示进度条的view的布局文件:head.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/head_rootLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<!-- 内容 -->
<RelativeLayout
android:id="@+id/head_contentLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="30dp" >
<!-- 箭头图像、进度条 -->
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" >
<!-- 箭头 -->
<ImageView
android:id="@+id/head_arrowImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="@drawable/arrow"
/>
<!-- 进度条 -->
<ProgressBar
android:id="@+id/head_progressBar"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone" />
</FrameLayout>
<!-- 提示、最近更新 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:orientation="vertical" >
<!-- 提示 -->
<TextView
android:id="@+id/head_tipsTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下拉刷新"
android:textColor="#ffffff"
android:textSize="20sp" />
<!-- 最近更新 -->
<TextView
android:id="@+id/head_lastUpdatedTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="最近更新"
android:textColor="#cc6600"
android:textSize="10sp" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
在重写listView实现onScrollListener
public class MyListView extends ListView implements OnScrollListener
{
/**
* 下拉现实的headView
*/
private View headView;
/**
* 刷新的箭头的view
*/
private ImageView arrowImageView;
/**
* 显示刷新的进度条
*/
private ProgressBar progressBar = null;
/**
* 显示提示刷新的提示语句
*/
private TextView tipsTextView;
/**
* 显示的第一个Item的view
*/
private int fistVisibleItem = -1;
/**
* headView的宽度
*/
private int headContextWidth=0;
/**
* 向下箭头的样式
*/
private Animation todownAnimation;
/**
* 向上箭头的样式
*/
private Animation toupAnimation;
/**
* headView的高度
*/
private int headContextHeight = 0;
/**
* 定义当前滑动的状态
*/
private int state = DONE;
/**
* 未执行的状态
*/
private static final int DONE = 0;
/**
* 即将松开去刷新界面,箭头变为向上
*/
private static final int RELEATSE_TO_FRESH = 1;
/**
* 正在加载数据
*/
private static final int LOADING = 2;
/**
* 拉动去刷新,调整箭头的位置,箭头向下
*/
private static final int PULL_TO_REFRESH = 3;
/**
* 确定当前只有一个开始的位置被记录
*/
private boolean isRecorded = false;
/**
* 设置滑动的比例
*/
private static final int FLING_V = 3;
/**
* 开始的位置
*/
private int starty =0;
private boolean isback = false;
/**
* 刷新界面的回调接口
*/
private OnRefreshListener onRefreshListener;
public interface OnRefreshListener
{
public void onRefresh();
}
public MyListView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
initView();
}
public MyListView(Context context, AttributeSet attrs)
{
super(context, attrs);
initView();
}
public MyListView(Context context)
{
super(context);
initView();
}
/**
* 初始化要显示的headview
*
* @see intView
*/
private void initView()
{
headView = ((LayoutInflater)getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.head, null);
arrowImageView = (ImageView)headView.findViewById(R.id.head_arrowImageView);
progressBar = (ProgressBar)headView.findViewById(R.id.head_progressBar);
tipsTextView = (TextView)headView.findViewById(R.id.head_tipsTextView);
//重新设置headView的大小
resetHeadView();
headContextWidth = headView.getMeasuredWidth();
headContextHeight = headView.getMeasuredHeight();
//设置headView的padding
headView.setPadding(0, -headContextHeight, 0, 0);
headView.invalidate();
//添加headView到listView的第一个item中去
addHeaderView(headView,null,false);
setOnScrollListener(this);
todownAnimation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
todownAnimation.setInterpolator(new LinearInterpolator());
todownAnimation.setDuration(250);
todownAnimation.setFillAfter(true);
toupAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
toupAnimation.setInterpolator(new LinearInterpolator());
toupAnimation.setDuration(250);
toupAnimation.setFillAfter(true);
state = DONE;
isRecorded = false;
}
/**
* 实现listView的触摸的事件
*
* @param ev
*
* 点击的事件
*
* @see onTouchEvent
*/
@Override
public boolean onTouchEvent(MotionEvent ev)
{
int tempy = 0;
switch(ev.getAction())
{
//点击的事件
case MotionEvent.ACTION_DOWN:
if(fistVisibleItem ==0 && !isRecorded)
{
isRecorded = true;
starty = (int)ev.getY();
}
break;
//移动的事件
case MotionEvent.ACTION_MOVE:
tempy = (int)ev.getY();
if(fistVisibleItem ==0 && !isRecorded)
{
isRecorded = true;
starty = (int)ev.getY();
}
//当前的用户不在加载数据,并且不在刷新界面的时候
if(state != LOADING && isRecorded)
{
//可以松开去刷新界面了
if(state == RELEATSE_TO_FRESH)
{
setSelection(0);
//用户在向上推的时候
if((tempy-starty)/FLING_V0)
{
state = PULL_TO_REFRESH;
changeHeadViewState();
}
//用户快速向上推
else if(tempy-startyheadContextHeight)
{
isback = true;
state = RELEATSE_TO_FRESH;
changeHeadViewState();
}
//上推到顶了
else if((tempy-starty)/FLING_V0)
{
state = PULL_TO_REFRESH;
changeHeadViewState();
}
}
//修改显示view的大小
if(state == PULL_TO_REFRESH||state == RELEATSE_TO_FRESH)
{
headView.setPadding(0, -headContextHeight+(tempy-starty)/FLING_V, 0, 0);
}
}
break;
//手势离开控件
case MotionEvent.ACTION_UP:
if(state != LOADING)
{
if(state == PULL_TO_REFRESH)
{
state = DONE;
changeHeadViewState();
}
else if(state == DONE)
{
}
else if(state == RELEATSE_TO_FRESH)
{
state = LOADING;
changeHeadViewState();
//刷新界面
onRefresh();
}
}
isRecorded = false;
break;
}
return super.onTouchEvent(ev);
}
/**
* 刷新界面的数据
*
* @see onRefresh
*/
private void onRefresh()
{
if(null != onRefreshListener)
{
onRefreshListener.onRefresh();
}
}
/**
* 界面刷新结束
*
* @see complete
*/
public void complete()
{
state = DONE;
changeHeadViewState();
}
/**
* 根据状态修改headView
*
* @see changeHeadViewState
*/
private void changeHeadViewState()
{
switch(state)
{
//箭头向上
case RELEATSE_TO_FRESH:
arrowImageView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
tipsTextView.setVisibility(View.VISIBLE);
arrowImageView.clearAnimation();
arrowImageView.startAnimation(toupAnimation);
Log.e(VIEW_LOG_TAG, "RELEATSE_TO_FRESH");
tipsTextView.setText("松开刷新");
break;
//箭头向下
case PULL_TO_REFRESH:
arrowImageView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
tipsTextView.setVisibility(View.VISIBLE);
if(isback)
{
Log.e(VIEW_LOG_TAG, "PULL_TO_REFRESH");
arrowImageView.clearAnimation();
arrowImageView.startAnimation(todownAnimation);
isback = false;
}
tipsTextView.setText("下拉刷新");
break;
case DONE:
headView.setPadding(0, -headContextHeight, 0, 0);
arrowImageView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
tipsTextView.setVisibility(View.VISIBLE);
arrowImageView.clearAnimation();
tipsTextView.setText("下拉刷新");
break;
//正在现在插件
case LOADING:
headView.setPadding(0,0, 0, 0);
arrowImageView.setVisibility(View.GONE);
progressBar.setVisibility(View.VISIBLE);
tipsTextView.setVisibility(View.VISIBLE);
arrowImageView.clearAnimation();
tipsTextView.setText("正在刷新");
break;
default:
break;
}
}
/**
* 重新设置headView的大小
*
* @see resetHeadView
*/
private void resetHeadView()
{
ViewGroup.LayoutParams layoutParams = headView.getLayoutParams();
if(null == layoutParams)
{
layoutParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);
}
int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, layoutParams.width);
int tempHeight = layoutParams.height;
int childHeightSpec=0;
if(tempHeight>0)
{
childHeightSpec=MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.EXACTLY);
}
else
{
childHeightSpec=MeasureSpec.makeMeasureSpec(tempHeight, MeasureSpec.UNSPECIFIED);
}
headView.measure(childWidthSpec, childHeightSpec);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState)
{
}
/**
* listView滑动的时候获取第一个显示的item
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
fistVisibleItem = firstVisibleItem;
}
public void setOnRefreshListener(OnRefreshListener onRefreshListener)
{
this.onRefreshListener = onRefreshListener;
}
}
上传一张显示的箭头的图片,这是重其它地方搞来的