Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義控件--下拉刷新的實現

Android自定義控件--下拉刷新的實現

編輯:關於Android編程

我們在使用ListView的時候,很多情況下需要用到下拉刷新的功能。為了了解下拉刷新的底層實現原理,我采用自定義ListView控件的方式來實現效果。

實現的基本原理是:自定義ListView,給ListView加載頭布局,然後動態的控制頭布局的現實與隱藏。ListView初始化的時候,頭布局是隱藏的,當手指往下拉的時候,根據手指移動的距離與頭布局的高度的關系來控制頭布局的顯示。具體的控制思路詳見後邊的代碼,代碼中的注釋很詳細。先來看一下效果圖:

\ \ \

 

頭布局的實現代碼如下:

 




    

        

        
        
    

    

        

        
    

 

接著定義一個RefreshListView,繼承自ListView,重寫它的三個構造方法,在RefreshlistView初始化的時候,加載一個頭布局,這個頭布局默認是隱藏的。

	// 初始化頭布局
	private void initHeaderView() {
		// 給當前的ListView添加下拉刷新的頭布局
		mHeaderView = View.inflate(getContext(), R.layout.list_refresh_header,
				null);
		tvTitle = (TextView) mHeaderView.findViewById(R.id.tv_title);
		tvTime = (TextView) mHeaderView.findViewById(R.id.tv_time);
		// 下拉箭頭
		ivArror = (ImageView) mHeaderView.findViewById(R.id.iv_arror);
		// 進度條
		pb = (ProgressBar) mHeaderView.findViewById(R.id.pb_list);

		this.addHeaderView(mHeaderView);
		// 初始化這個下拉刷新的ListView的時候,縣隱藏掉下拉刷新的頭布局,然後通過代碼動態的控制頭布局的顯示與隱藏
		// 隱藏頭布局
		// 先測量一把頭布局
		mHeaderView.measure(0, 0);
		// 獲得測量得到的高度
		mHeaderViewHeight = mHeaderView.getMeasuredHeight();
		// 設置paddingtop為負高度,隱藏頭布局
		mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);

		// 初始化完成布局,初始化兩個動畫效果

		initAnimation();
		// 設置當前時間
		tvTime.setText("最後刷新時間:" + getCurrentTime());
	}

當手指觸摸屏幕時,觸發OnTouchEvent事件,根據手指在Y軸方向上的移動偏移量來動態的控制頭布局的顯示與隱藏。並即時更新下拉框的顯示的狀態。具體的代碼如下:

	/**
	 * 下拉屏幕的時候,將頭布局展示出來,重寫一下ListView的觸摸屏幕的事件
	 */
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			// 手指按下的時候獲得當前屏幕的Y坐標
			startY = (int) ev.getRawY();

			break;
		case MotionEvent.ACTION_MOVE:
			// 手指移動的時候,獲得當前屏幕的Y坐標,與開始的Y坐標做比較

			if (startY == -1) {
				// 確保startY有效
				startY = (int) ev.getRawY();
			}

			int endY = (int) ev.getRawY();
			// 屏幕Y方向移動的距離
			int dy = endY - startY;
			// 只有屏幕向下滑,也就是dy>0,並且當前的ListView顯示的是第一個條目,那個隱藏的下拉刷新的頭布局才慢慢的隨手指滑出來
			if (dy > 0 && this.getFirstVisiblePosition() == 0) {
				// 允許下拉刷新框出來
				// 下拉刷新框出來其實就是給頭布局設置padding,首先根據手指移動的距離計算一下padding
				int padding = dy - mHeaderViewHeight;//
				mHeaderView.setPadding(0, padding, 0, 0);
				// 更新刷新框的狀態
				// 一共有三種狀態,下拉刷新、正在刷新、松開刷新
				// 定義這三種狀態
				// 如果padding大於0說明下拉刷新的框已經全部拉出來了,將狀態改為松開刷新
				if (padding > 0 && mCurrentState != STATE_RELEASE_REFRESH) {
					// 狀態改為松開刷新,將下拉框顯示的狀態更新一下
					mCurrentState = STATE_RELEASE_REFRESH;
					// 更新當前下拉框顯示的狀態
					updateState();
				}
				if (padding < 0 && mCurrentState != STATE_PULL_REFRESH) {
					// 狀態改為下拉刷新
					mCurrentState = STATE_PULL_REFRESH;
					updateState();
				}

			}

			break;
		case MotionEvent.ACTION_UP:
			// 手指抬起來的時候重置startY。將狀態改為正在刷新
			startY = -1;
			if (mCurrentState == STATE_RELEASE_REFRESH) {
				// 如果當前為松開刷新,則手指一抬起來就將狀態改為正在
				mCurrentState = STATE_REFRESHING;
				// 頭布局的padding設置為0000
				mHeaderView.setPadding(0, 0, 0, 0);
				updateState();
			} else {
				// 沒有完全拉出來,就將頭布局隱藏
				mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);

			}

			break;

		}

		return super.onTouchEvent(ev);
	}

	/**
	 * 更新當前下拉框顯示的狀態
	 */
	private void updateState() {
		// 判斷當前狀態是什麼,根據當前狀態更新下拉框顯示
		switch (mCurrentState) {
		case STATE_PULL_REFRESH:
			// 下拉刷新
			tvTitle.setText("下拉刷新");
			ivArror.setVisibility(View.VISIBLE);
			pb.setVisibility(View.INVISIBLE);
			// 給箭頭設置動畫
			ivArror.startAnimation(animDown);
			break;

		case STATE_REFRESHING:
			// 正在刷新
			tvTitle.setText("正在刷新...");
			ivArror.clearAnimation();// 必須先清除動畫,才能隱藏
			ivArror.setVisibility(View.INVISIBLE);
			pb.setVisibility(View.VISIBLE);
			// 正在刷新的時候調用接口中的方法
			if (mListener != null) {
				// 正在刷新
				mListener.onRefresh();
			}

			break;

		case STATE_RELEASE_REFRESH:
			// 松開刷新
			tvTitle.setText("松開刷新");
			ivArror.setVisibility(View.VISIBLE);
			pb.setVisibility(View.INVISIBLE);
			ivArror.startAnimation(animUp);
			break;
		}

	}

為了監聽下拉刷新的動作,自定義一個監聽接口,當正在刷新的時候執行onRefresh方法。對外提供一個設置監聽的方法,監聽器由子類實現,具體的正在刷新執行的邏輯由子類在onRefresh中實現。

// 下拉刷新邏輯的實現方式:給當前的ListView設置下拉刷新的監聽器,監聽器的本質就是一個接口
	/**
	 * 下拉刷新的監聽器
	 * 
	 * @author ZHY
	 * 
	 */
	public interface onRefreshListener {
		// 刷新的時候執行的方法,誰實現這個接口。誰執行此方法
		public void onRefresh();

	}

	onRefreshListener mListener;

	// 有了監聽器之後,提供一個設置監聽的方法
	public void setOnRefreshListener(onRefreshListener listener) {
		// 這個Listneer是從子類中闖過來的,是子類定義的監聽
		mListener = listener;
	}

刷新完成之後,改變下拉刷新的狀態,並且隱藏下拉框

	// 刷新完成的時候,將下拉框隱藏
	/**
	 * 調用服務器的數據刷新,刷新完成之後調用的方法 加載完成之後的回調
	 * 
	 * @param isSuccess
	 */
	public void onRefreshCompleted(boolean isSuccess) {

		// 將狀態改成下拉刷新,然後隱藏下拉框
		mCurrentState = STATE_PULL_REFRESH;
		tvTitle.setText("下拉刷新");
		ivArror.setVisibility(View.VISIBLE);
		pb.setVisibility(View.INVISIBLE);

		mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隱藏
		// 如果刷新成功,則更新最後一次刷新時間,否則不更新時間
		if (isSuccess) {
			tvTime.setText("最後刷新時間:" + getCurrentTime());

		}

	}

這一部分工作做完之後,一個可以實現下拉刷新功能的ListView就定義好了。在MainActivity中就可以直接使用了

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved