Android下拉刷新

PTRListView.java

public class PTRListView extends ListView implements OnScrollListener {
    private static final int PULL_TO_REFRESH = 0;
    private static final int RELEASE_TO_REFRESH = 1;
    private static final int REFRESHING = 2;
    private static final int DONE = 3;

    // view组件
    private View mHeadView;
    private ImageView iv_header_ptrl_arrow;
    private ProgressBar pb_header_ptrl;
    private TextView tv_header_ptrl_tips;
    private TextView tv_header_ptrl_time;

    private int mHeadcontentHeight;
    private OnRefreshListener mOnRefreshListener;
    private Animation mPositiveAnimation;
    private Animation mNegativeAnimation;

    private int mFirstVisibleIndex;
    private int mState = DONE;
    private boolean mIsRecored = false;
    // 记录startY 起始位置 在整个滑动过程中,只记录一次
    private float mStartY;
    private boolean mIsUndo;

    public PTRListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public PTRListView(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        // 要在adapter中使用 ,在当前使用会报错 空指针
        // View headView = View.inflate(context, R.layout.header_ptrl, null);
        LayoutInflater inflater = LayoutInflater.from(context);
        mHeadView = inflater.inflate(R.layout.header_ptrl, null);
        iv_header_ptrl_arrow = (ImageView) mHeadView.findViewById(R.id.iv_header_ptrl_arrow);
        pb_header_ptrl = (ProgressBar) mHeadView.findViewById(R.id.pb_header_ptrl);
        tv_header_ptrl_tips = (TextView) mHeadView.findViewById(R.id.tv_header_ptrl_tips);
        tv_header_ptrl_time = (TextView) mHeadView.findViewById(R.id.tv_header_ptrl_time);

        iv_header_ptrl_arrow.setMinimumWidth(70);
        iv_header_ptrl_arrow.setMinimumHeight(50);

        measureView(mHeadView);
        mHeadcontentHeight = mHeadView.getMeasuredHeight();

        // 设置headView 与界面上边距的距离
        mHeadView.setPadding(0, -1 * mHeadcontentHeight, 0, 0);
        // 重绘
        mHeadView.invalidate();
        addHeaderView(mHeadView);
        setHeaderDividersEnabled(false);

        mPositiveAnimation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mPositiveAnimation.setDuration(300);
        mPositiveAnimation.setFillAfter(true);
        mPositiveAnimation.setInterpolator(new LinearInterpolator());// 设置动画速度
        /*
         * Interpolator 定义了动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等;
         * 
         * AccelerateDecelerateInterpolator,延迟减速,在动作执行到中间的时候才执行该特效。 AccelerateInterpolator, 会使慢慢以(float)的参数降低速度。 LinearInterpolator,平稳不变的 DecelerateInterpolator,在中间加速,两头慢 CycleInterpolator,曲线运动特效,要传递float型的参数。
         */
        mNegativeAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        mNegativeAnimation.setDuration(300);
        mNegativeAnimation.setFillAfter(true);
        mNegativeAnimation.setInterpolator(new LinearInterpolator());
    }

    // 测量Headview 宽高
    private void measureView(View child) {
        ViewGroup.LayoutParams lp = child.getLayoutParams();
        if (lp == null) {
            lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        }
        int childMeasureWidth = ViewGroup.getChildMeasureSpec(0, 0, lp.width);
        int childMeasureHeight;
        if (lp.height > 0) {
            childMeasureHeight = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);// 适合、匹配
        } else {
            childMeasureHeight = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);// 未指定
        }
        child.measure(childMeasureWidth, childMeasureHeight);
    }

    @SuppressWarnings("deprecation")
    public void onRefreshComplete() {
        mState = DONE;
        changeHeadViewState();
        tv_header_ptrl_time.setText("最近更新: " + new Date().toLocaleString());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (mOnRefreshListener != null) {
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (mFirstVisibleIndex == 0 && !mIsRecored) {
                    mStartY = event.getY();
                    mIsRecored = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                if (mIsRecored) {
                    float tempY = event.getY();
                    if (mState == DONE) {
                        if (tempY - mStartY > 0) {
                            // 刷新完成 --》 进入 下拉刷新
                            mState = PULL_TO_REFRESH;
                            mHeadView.setPadding(0, (int) (-1 * mHeadcontentHeight + tempY - mStartY), 0, 0);
                            changeHeadViewState();
                        }
                    } else if (mState == PULL_TO_REFRESH) {
                        if (tempY - mStartY >= mHeadcontentHeight) {
                            // 下啦刷新 --》 松开刷新
                            mState = RELEASE_TO_REFRESH;
                            changeHeadViewState();
                        } else if (tempY - mStartY <= 0) {
                            // 下啦刷新 --》 回到 刷新完成
                            mState = DONE;
                            changeHeadViewState();
                        } else {
                            mHeadView.setPadding(0, (int) (-1 * mHeadcontentHeight + tempY - mStartY), 0, 0);
                        }
                    } else if (mState == RELEASE_TO_REFRESH) {
                        if (tempY - mStartY < mHeadcontentHeight) {
                            // 松开刷新 --》回到下拉刷新
                            mState = PULL_TO_REFRESH;
                            mIsUndo = true;// 从松开刷新 回到的下拉刷新
                            changeHeadViewState();
                        }
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                if (mIsRecored) {
                    mIsRecored = false;
                    if (mState == PULL_TO_REFRESH) {
                        mState = DONE;
                        changeHeadViewState();
                    } else if (mState == RELEASE_TO_REFRESH) {
                        mState = REFRESHING;
                        changeHeadViewState();
                    }
                }
                break;
            }
        }
        return super.onTouchEvent(event);
    }

    // headview状态改变
    private void changeHeadViewState() {
        switch (mState) {
        case PULL_TO_REFRESH:
            iv_header_ptrl_arrow.setVisibility(View.VISIBLE);
            pb_header_ptrl.setVisibility(View.GONE);

            tv_header_ptrl_tips.setText("下拉刷新");
            iv_header_ptrl_arrow.clearAnimation();

            // 从松开刷新 回到 下拉刷新,即不执行刷新操作
            if (mIsUndo) {
                iv_header_ptrl_arrow.startAnimation(mPositiveAnimation);
                mIsUndo = false;
            }
            break;
        case RELEASE_TO_REFRESH:
            iv_header_ptrl_arrow.setVisibility(View.VISIBLE);
            pb_header_ptrl.setVisibility(View.GONE);

            tv_header_ptrl_tips.setText("松开刷新");
            iv_header_ptrl_arrow.clearAnimation();
            iv_header_ptrl_arrow.startAnimation(mNegativeAnimation);

            mHeadView.setPadding(0, 0, 0, 0);
            break;
        case REFRESHING:
            iv_header_ptrl_arrow.setVisibility(View.GONE);
            pb_header_ptrl.setVisibility(View.VISIBLE);

            tv_header_ptrl_tips.setText("正在刷新中...");
            iv_header_ptrl_arrow.clearAnimation();

            mHeadView.setPadding(0, 0, 0, 0);

            onRefresh();
            break;
        case DONE:
            iv_header_ptrl_arrow.setVisibility(View.VISIBLE);
            pb_header_ptrl.setVisibility(View.GONE);

            tv_header_ptrl_tips.setText("下拉刷新");
            iv_header_ptrl_arrow.clearAnimation();

            mHeadView.setPadding(0, -1 * mHeadcontentHeight, 0, 0);
            break;

        }
    }

    // 刷新 得到服务器的数据
    private void onRefresh() {
        if (mOnRefreshListener != null) {
            mOnRefreshListener.onRefresh();
        }
    }

    // 提供一个对外访问的刷新方法
    public void setOnRefreshListener(OnRefreshListener listener) {
        mOnRefreshListener = listener;
    }

    public interface OnRefreshListener {
        public void onRefresh();
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        mFirstVisibleIndex = firstVisibleItem;
    }
}

header_ptrl.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/rl_header_ptrl_margin" >

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true" >

            <ImageView
                android:id="@+id/iv_header_ptrl_arrow"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:src="@drawable/arrow" />

            <ProgressBar
                android:id="@+id/pb_header_ptrl"
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="gone" />
        </FrameLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/tv_header_ptrl_tips"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginBottom="@dimen/tv_header_ptrl_tips_marginBottom"
                android:text="下拉刷新"
                android:textSize="@dimen/textSize_normal" />

            <TextView
                android:id="@+id/tv_header_ptrl_time"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="上一次修改的时间"
                android:textSize="@dimen/textSize_normal" />
        </LinearLayout>
    </RelativeLayout>

</LinearLayout>

 

posted @ 2014-04-01 17:24  bingoogolapple  阅读(333)  评论(0编辑  收藏  举报