編輯:關於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中就可以直接使用了
在這裡我們要使用Android ListView來實現顯示股票行情,效果圖如下,紅色表示股票價格上漲,綠色表示股票價格下跌。第一步、定義color.xml如下:復制代碼
Android Http 客戶端編程之GET 說起Http編程,不盡然想起GET和POST兩種請求方式,本文以簡潔明了的的步驟和說明,將Android中常用
在android開發中,如果在一個線程中想更新主界面中控件顯示的數據,直接給主界面控件賦值就會出現異常,android中為了安全起見,是不允許在線程中更新界面控件的數據,
最近在參加CSDN博客之星,希望大家給投一票,謝謝啦~ 點這裡投我一票吧~前言 在開發當中,我們常常需要實現文件上傳,比較常