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

Android---可以實現下拉刷新的ListView

編輯:關於Android編程

1.效果

這裡寫圖片描述
這個效果在很多App裡都可以用到,基本上就已經泛濫了.這裡就記錄一下如何實現這一種效果.(截圖沒注意大小,丟幀也嚴重,所以看上去有點卡頓)

2.實現步驟

2.1布局文件
這裡寫圖片描述
首先要明確的是,這一塊也是一個布局文件,我們首先寫出這個layout,代碼比較簡單,就不做說明了:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxzdHJvbmc+cHVsbF90b19yZWZlc2gueG1sPC9zdHJvbmc+PC9wPg0KPHByZSBjbGFzcz0="brush:java;"> <framelayout android:layout_height="wrap_content" android:layout_width="wrap_content" android:padding="10dp"> </framelayout>

2.2創建一個類繼承自ListView

public class PullToRefreshListView extends ListView {}

在這個類裡面,我們去實現下拉刷新.

2.3 initView()

    private void initView() {
            mHeaderView = View.inflate(getContext(), R.layout.pull_to_refesh, null);

        //作為ListView 的headerView
        this.addHeaderView(mHeaderView);

        tv_title = (TextView) mHeaderView.findViewById(R.id.tv_title);
        tv_time = (TextView) mHeaderView.findViewById(R.id.tv_time);
        iv_arrow = (ImageView) mHeaderView.findViewById(R.id.iv_arrow);
        pb_loading = (ProgressBar) mHeaderView.findViewById(R.id.pb_loading);


        //隱藏掉下拉刷新的頭布局
        mHeaderView.measure(0, 0);
        mHeaderViewHeight = mHeaderView.getMeasuredHeight();
        mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);

        //初始化Animation
        initAnimation();

        //初始化現在時間
        setCurrentTime();
    }

2.3.1
在這個方法裡,我們將pull_to_refesh.xml轉換成的view對象mHeaderView,作為headerView設置給當前自定義的ListView

this.addHeaderView(mHeaderView);

2.3.2
再將mHeaderView隱藏起來:

        mHeaderView.measure(0, 0);
        mHeaderViewHeight = mHeaderView.getMeasuredHeight();
        mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);

2.3.3
初始化動畫的方法,在效果圖中,我們可以看到,當下拉刷新時候,向下的箭頭會有一個180度的旋轉動畫:

private void initAnimation() {
        mRotateAnimationUp = new RotateAnimation(0, 180,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        mRotateAnimationUp.setDuration(2000);
        mRotateAnimationUp.setFillAfter(true);

        mRotateAnimationDown = new RotateAnimation(180,0,
                Animation.RELATIVE_TO_SELF, 0.5f,
                Animation.RELATIVE_TO_SELF, 0.5f);
        mRotateAnimationDown.setDuration(2000);
        mRotateAnimationDown.setFillAfter(true);
    }

2.3.4
刷新後設置時間的方法:

public void setCurrentTime(){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = simpleDateFormat.format(new Date());
        tv_time.setText(time);
    }

2.4重寫onTouchEvent()方法
先貼出方法,在分析

@Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mStartY = (int) ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                mEndY = (int) ev.getY();
                //當用戶按住頭條新聞的ViewPager下來時,ACTION_DOWN事件會被ViewPager消耗,導致mStartY沒有被賦值
                //所以在此處需要重新的拿Y值
                if (mStartY == -1) {
                    mStartY = (int) ev.getY();
                }

                //如果現在的狀態是正在刷新,那麼直接跳出循環
                if (mCurrentState==ConstantValues.STATE_REFRESHING){
                    break;
                }
                //在Y方向上的偏移量
                int dy = mEndY - mStartY;

                //拿到當前顯示的第一個item的位置
                int firstVisiblePosition = getFirstVisiblePosition();

                Log.d("firstVisiblePosition------>",firstVisiblePosition+"");

              //下拉&&當前顯示的是第一個item (mHeaderView)
                if (dy > 0 && firstVisiblePosition == 0) {

                    int padding = dy - mHeaderViewHeight;

                    Log.d("------>", "dy--->" + dy + "--->mHeaderViewHeight" + mHeaderViewHeight + "--->padding" + padding);

                    mHeaderView.setPadding(0, padding, 0, 0);

                    if (padding > 0 && mCurrentState != ConstantValues.STATE_RELEASE_TO_REFRESH) {
                        //改為松開刷新
                        mCurrentState = ConstantValues.STATE_RELEASE_TO_REFRESH;
                        refreshState();

                    } else if (padding < 0 && mCurrentState != ConstantValues.STATE_PULL_TO_REFRESH) {
                        //改為下拉刷新
                        mCurrentState = ConstantValues.STATE_PULL_TO_REFRESH;
                        refreshState();
                    }

                    return true;

                }

                break;
            case MotionEvent.ACTION_UP:
                //為下一次刷新做准備,重新賦值為-1
                mStartY=-1;

                if (mCurrentState==ConstantValues.STATE_RELEASE_TO_REFRESH){
                    mCurrentState=ConstantValues.STATE_REFRESHING;
                    refreshState();
                    //完整展示頭布局
                    mHeaderView.setPadding(0,0,0,0);


                    /**
                    *4.(合適的時機)進行回調
                    *@author zfy
                    *@created at 2016/7/12 14:23
                    */
                    if (mListener!=null){
                        mListener.onRefresh();
                    }

                }else if (mCurrentState==ConstantValues.STATE_PULL_TO_REFRESH){
                    //隱藏頭布局
                    mHeaderView.setPadding(0,-mHeaderViewHeight,0,0);
                }


                break;
        }


        return super.onTouchEvent(ev);
    }

首先會有mCurrentState這個量,表示的是下拉欄當前的狀態

 1.STATE_PULL_TO_REFRESH=1;表示目前處於需要被下拉的狀態
 2.STATE_RELEASE_TO_REFRESH=2;表示目前處於需要松手的狀態
 3.STATE_REFRESHING=3;表示目前處於正在刷新的狀態

ACTION_DOWN時候拿到當前的Y值mStartY = (int) ev.getY();默認等於-1

ACTION_MOVE時候:我們根據當前下拉的位置padding,重新設置mHeaderView的padding值.並修改當前的下拉狀態

ACTION_UP的時候:對mStartY重新賦值,並且進行回調.

其中根據狀態值重新刷新界面的方法refreshState如下:
 private void refreshState() {
        switch (mCurrentState) {
            case ConstantValues.STATE_PULL_TO_REFRESH:
                tv_title.setText("下拉刷新");
                iv_arrow.startAnimation(mRotateAnimationDown);
                pb_loading.setVisibility(View.INVISIBLE);
                iv_arrow.setVisibility(View.VISIBLE);
                break;
            case ConstantValues.STATE_RELEASE_TO_REFRESH:
                tv_title.setText("松開刷新");
                iv_arrow.startAnimation(mRotateAnimationUp);
                pb_loading.setVisibility(View.INVISIBLE);
                iv_arrow.setVisibility(View.VISIBLE);
                break;
            case ConstantValues.STATE_REFRESHING:
                tv_title.setText("正在刷新...");

                //清除箭頭動畫,否則不能隱藏
                iv_arrow.clearAnimation();

                pb_loading.setVisibility(View.VISIBLE);
                iv_arrow.setVisibility(View.INVISIBLE);
                break;
        }

    }

2.5回調

定義下拉刷新的接口 暴露接口設置監聽 定義成員變量接收監聽對象 在合適的時機進行回調 在前端邏輯界面設置回調
   /**
     * 3.定義成員變量接收監聽對象
     *
     * @author zfy
     * @created at 2016/7/12 14:09
     */
    private OnRefreshListener mListener;

    /**
     * 2.暴露接口設置監聽
     *
     * @author zfy
     * @created at 2016/7/12 14:08
     */
    public void setOnRefreshListener(OnRefreshListener listener) {
        mListener = listener;
    }

    /**
     * 1.下拉刷新的回調接口
     *
     * @author zfy
     * @created at 2016/7/12 14:06
     */
    public interface OnRefreshListener {
        public void onRefresh();
    }

步驟4在onTouchEvent方法中實現
步驟5在前段從服務器再次請求數據時候調用

/**
         *5.前端界面設置回調
         *@author zfy
         *@created at 2016/7/12 14:14
         */
        lv_list.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener() {
            @Override
            public void onRefresh() {

                //從服務器中重新拿數據的方法
                getDataFromServer();

            }
        });

2.6刷新數據之後,隱藏下拉刷新頭View的方法

 /**
    *刷新完成後收起頭View的方法
    *@author zfy
    *@return
    *@param success 是否成功刷新
    *@created at 2016/7/12 14:56
    */
    public void onRefreshComplete(boolean success){
        mHeaderView.setPadding(0,-mHeaderViewHeight,0,0);
        tv_title.setText("下拉刷新");
        mCurrentState=ConstantValues.STATE_PULL_TO_REFRESH;
        pb_loading.setVisibility(INVISIBLE);
        iv_arrow.setVisibility(VISIBLE);
        if (success) {

            setCurrentTime();
        }
    }

這個方法在回調步驟5,重新從服務器拿數據方法getDataFromServer()內部調用

三.補充

上述步驟完成之後,下拉刷新的方法基本就已經實現了. 下拉刷新的實現過程也差不多就是一個簡單的自定義View的過程 這個功能也大可不必自己手敲,很多開源類庫都已經實現了這個功能.
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved