Android菜鸟之listview下拉刷新

《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
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值