zoukankan      html  css  js  c++  java
  • 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>
  • 相关阅读:
    mysql 函数在源码中的定义
    mydumper工作原理 :myownstars专家
    drop table big_table 调试
    debugfs恢复文件
    Linux内核里的DebugFS
    在Linux环境中使用Ext3文件系统
    strace
    通过blktrace, debugfs分析磁盘IO
    block_dump观察Linux IO写入的具体文件(mysqld)
    Centos下的IO监控与分析
  • 原文地址:https://www.cnblogs.com/bingoogol/p/PTRListView.html
Copyright © 2011-2022 走看看