《1》首先我们要写一个自定义的listview(写一个类继承ListView类)
public class RefreshListView extends ListView
然后我们需要填充这个RefreshListView
class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
return dataList.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv = new TextView(MainActivity.this);
tv.setText(dataList.get(position));
tv.setTextSize(18);
return tv;
}
}
显示基本的数据列表
2》自定义RefreshListView 的头
/**
* 初始化ListView的頭佈局
*/
private void initHeader() {
headView=LayoutInflater.from(getContext()).inflate(R.layout.listview_header, null);
ivArrow = (ImageView) headView.findViewById(R.id.iv_listview_header_arrow);//
ivArrow.setMinimumWidth(70);
tvState = (TextView) headView.findViewById(R.id.tv_listview_header_state);
tvLastUpdateTime = (TextView) headView.findViewById(
R.id.tv_listview_header_last_update_time);
mProgressBar = (ProgressBar) headView.findViewById(
R.id.pb_listview_header_arrow);
headView.measure(0, 0);//测量头布局的宽和高
headerViewHeight = headView.getMeasuredHeight();//布局的高度155
Log.i(TAG,"头布局的高度:"+headerViewHeight);
headView.setPadding(0,-headerViewHeight,0,0);
addHeaderView(headView);
initAnimation();
}
用到的 listview_header.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dip" >
<ImageView
android:id="@+id/iv_listview_header_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/common_listview_headview_red_arrow" />
<ProgressBar
android:id="@+id/pb_listview_header_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone"
android:indeterminateDrawable="@drawable/custom_prograssbar"/>
</FrameLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_horizontal"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_listview_header_state"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="下來刷新"
android:textColor="#FF0000"
android:textSize="18sp" />
<TextView
android:id="@+id/tv_listview_header_last_update_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="最后刷新时间:1990-09-09 09:09:09"
android:textColor="@android:color/darker_gray"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
接下来我们要理解下拉的逻辑:
1)首先我们需要隐藏listView的头
2)实现public boolean onTouchEvent(MotionEvent ev) {
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN://下拉事件
downY = (int)ev.getY();
break;
case MotionEvent.ACTION_MOVE:
int moveY=(int) ev.getY();//移动中Y轴的偏移量
// Log.i(TAG, "移動:"+moveY);
// Log.i(TAG,"下移動:"+downY);
int diffY=moveY-downY/3;
// Log.i(TAG,"diffY:"+diffY);
int paddingTop=-headerViewHeight+diffY;
if(mfirstVisibleItem==0 && paddingTop>-headerViewHeight){//當前是在顶部
if(paddingTop>0&¤tState==DOWN_REFRESH){//下拉刷新
Log.i(TAG,"完全显示了,可以松开刷新了");
currentState=RELEASE_REFRESH;//鬆開刷新
refreshHeaderViewState();
}else if(paddingTop<0&¤tState==RELEASE_REFRESH){//正在刷新中
Log.i(TAG,"没有完全显示,当前是下拉刷新");
currentState=DOWN_REFRESH;
refreshHeaderViewState();
}
headView.setPadding(0,paddingTop, 0, 0);
return true;
}
headView.setPadding(0,paddingTop, 0,0);
break;
case MotionEvent.ACTION_UP:
if(currentState==DOWN_REFRESH){//下拉刷新抬起手指,需要把头布局隐藏
headView.setPadding(0,-headerViewHeight, 0, 0);
}else if(currentState==RELEASE_REFRESH){//释放刷新 ,显示正在刷新中的状态
currentState=REFRESHING;//正在刷新中
refreshHeaderViewState();//刷新头布局的状态
/**
* 去掉边距
*/
headView.setPadding(0, 0, 0, 0);
if(mOnRefreshListener!=null){
mOnRefreshListener.onDownRefresh();//刷新数据
}
//刷新完数据后 头隐藏
}
break;
default:
break;
}
return super.onTouchEvent(ev);
}
3)计算滑动的距离,同时显示头
int paddingTop=-headerViewHeight+diffY;
4)自定义动画修改箭头(两个箭头转动的动画)
private void initAnimation() {
upAnimation = new RotateAnimation(0, -180
, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(500);
upAnimation.setFillAfter(true);//停留在动画结束时
downAnimation = new RotateAnimation(-180,-360
, Animation.RELATIVE_TO_SELF, 0.5f,
Animation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(500);
upAnimation.setFillAfter(true);//停留在动画结束时
}
5)开始编写回调函数(判断头是否全部显示,然后加载数据,加载数据的同时修改图片为sing)
public interface OnRefreshListener {
/**
* 当下拉刷新时回调
*/
public void onDownRefresh();
/**
* 当加载更多时回调
*/
public void onLoadMoring();
}
主界面加载数据/**
* 异步加载数据
*/
@Override
public void onLoadMoring() {
//异步去抓取数据
new AsyncTask<Void, Void, Void>(){
@Override
protected Void doInBackground(Void... params) {
SystemClock.sleep(2000);
dataList.add("这是加载更多的数据1");
dataList.add("这是加载更多的数据2");
dataList.add("这是加载更多的数据3");
return null;
}
@Override
protected void onPostExecute(Void result) {
mAdapter.notifyDataSetChanged();
mRefreshListView.hideFooterView();//隐藏脚布局
super.onPostExecute(result);
}
}.execute(new Void[]{});
}
6)数据加载完毕,隐藏工作
/**
* 隐藏头布局
*/
public void hideHeaderView(){
headView.setPadding(0, -headerViewHeight, 0, 0);
mProgressBar.setVisibility(View.GONE);
mProgressBar.clearAnimation();
ivArrow.setVisibility(View.VISIBLE);
tvState.setText("下来刷新");
tvLastUpdateTime.setText("最后刷新时间:"+getLastUpdateTime());
currentState=DOWN_REFRESH;
}
7)自定义监听
/**
* 设置刷新的监听事件
* 刷新完之后需要用hideHeaderView(),隐藏头buju
* @param listener
*/
public void setOnRefreshListener(OnRefreshListener listener){
this.mOnRefreshListener=listener;
}
8)细节:/**
* 当滚动状态改变时回调
* SCroll_state_idle 停止状态
* scroll_state_touch_scroll 触摸滚动(按住移动)
* scroll_state_fing 滚动滑动
*/
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState==SCROLL_STATE_IDLE||
scrollState==SCROLL_STATE_FLING){
if(isScrollToBottom && !isLoadMoring){
isLoadMoring=true;//加载更多中
Log.i(TAG,"滑動到底部");
footerView.setPadding(0, 0, 0, 0);//显示脚布局
//滚动到底部,使用脚布局显示
this.setSelection(this.getCount());
//调用注册监听事件
if(mOnRefreshListener!=null){
mOnRefreshListener.onLoadMoring();
}
}
}
}
/**
* 当ListView滚动时回调方法
*
* @param firstVisibleItem
* 当前屏幕第一个可见的item的索引
* @param visibleItemCount
* 当前屏幕显示了多少个item的数量
* @param totalItemCount
* listView的总长度
*/
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
mfirstVisibleItem = firstVisibleItem;
if ((firstVisibleItem + visibleItemCount) == (totalItemCount)) {// 判断是否滚动到底部
// Log.i(TAG, "滚动到底部,滚动到底部,滚动到底部,滚动到底部");
isScrollToBottom = true;
} else {
isScrollToBottom = false;
}
}
源代码下载:http://download.csdn.net/detail/javamov/6948855