一个Android下拉刷新样式

近来需求要求下拉刷新动画Android和iOS统一样式, 效果如下:

一个Android下拉刷新样式_第1张图片
下拉刷新gif

使用SmartRefreshLayout这个框架自定义Header动画. 感觉这个框架还是很好用的.

  1. SmartRefreshLayout加入到项目:

    compile 'com.android.support:appcompat-v7:25.3.1'
    compile 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.2-alpha-5'
    
  2. 在自定义的Application文件里初始化:

    public class App extends Application {
        @Override
        public void onCreate() {
            super.onCreate();
            initRefreshViewLayout();
        }
    
        private void initRefreshViewLayout() {
            MyRefreshLayout.init();
        }
    }
    
  3. 自定义个继承自SmartRefreshLayoutMyRefreshLayout文件:

    public class MyRefreshLayout extends SmartRefreshLayout {
        public static void init() {
            // 指定全局的下拉Header
            SmartRefreshLayout.setDefaultRefreshHeaderCreater(new DefaultRefreshHeaderCreater() {
                @Override
                public RefreshHeader createRefreshHeader(Context context, RefreshLayout layout) {
                    return new MyRefreshHeader(context);
                }
            });
    
            // 指定全局的上拉Footer
            SmartRefreshLayout.setDefaultRefreshFooterCreater(new DefaultRefreshFooterCreater() {
                @NonNull
                @Override
                public RefreshFooter createRefreshFooter(Context context, RefreshLayout layout) {
                    return new ClassicsFooter(context);
                }
            });
        }
    
        public MyRefreshLayout(Context context) {
            super(context);
            initView(context);
        }
    
        public MyRefreshLayout(Context context, AttributeSet attrs) {
            super(context, attrs);
            initView(context);
        }
    
        public MyRefreshLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView(context);
        }
    
        private void initView(Context context) {
            setReboundDuration(300); // 设置回弹动画时长
            setPrimaryColorsId(R.color.white);  // 主题色
            setEnableAutoLoadmore(false); // 设置是否监听列表在滚动到底部时触发加载事件
    
        }
    
        // 下拉/上拉完成
        public void complete() {
            if (mState == RefreshState.Loading) {
                finishLoadmore();
            } else {
                finishRefresh();
            }
        }
    }
    
  4. 创建个MyRefreshHeader文件, 在这里做自定义的动画:

    public class MyRefreshHeader extends RelativeLayout implements RefreshHeader {
        private CircleProgressView mCircleProgressView;
        private TextView mTextView;
        private ImageView mArrow;
        private boolean isArrowDown = false;
    
        public MyRefreshHeader(Context context) {
            super(context);
            this.initView(context, null, 0);
        }
    
        public MyRefreshHeader(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.initView(context, attrs, 0);
        }
    
        public MyRefreshHeader(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            this.initView(context, attrs, defStyleAttr);
        }
    
        private void initView(Context context, AttributeSet attrs, int defStyleAttr) {
            setMinimumHeight(dp2px(context, 80));
            LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            params.addRule(CENTER_IN_PARENT);
            View headerView = View.inflate(context, R.layout.my_refresh_header, null);
            mCircleProgressView = (CircleProgressView) headerView.findViewById(R.id.circleProgressView);
            mTextView = (TextView) headerView.findViewById(R.id.textview);
            mArrow = (ImageView) headerView.findViewById(R.id.iv_refresh_center);
            addView(headerView, params);
        }
    
        @Override
        public void onInitialized(RefreshKernel kernel, int height, int extendHeight) { // 尺寸定义完成
        }
    
        @Override
        public void onPullingDown(float percent, int offset, int headHeight, int extendHeight) { // 手指拖动下拉(会连续多次调用)
            if (mCircleProgressView == null) return;
            float startPercent = 0.20f;
    
            if (percent > startPercent && percent < 1) {
                float tempPercent = (percent-startPercent) * 1.0f / (1 - startPercent);
                mCircleProgressView.setProgressPersent(tempPercent);
            }
        }
    
        @Override
        public void onReleasing(float percent, int offset, int headHeight, int extendHeight) {  // 手指释放之后的持续动画
        }
    
        @Override
        public void onStartAnimator(RefreshLayout layout, int headHeight, int extendHeight) {
            RotateAnimation ta = new RotateAnimation(0, 360,
                    RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                    RotateAnimation.RELATIVE_TO_SELF, 0.5f);
            ta.setDuration(500);
            ta.setRepeatCount(10000);
            ta.setInterpolator(new LinearInterpolator());
            ta.setFillAfter(true);
            mCircleProgressView.startAnimation(ta);
        }
    
        @Override
        public int onFinish(RefreshLayout layout, boolean success) {
            mCircleProgressView.clearAnimation();
            return 100; // 动画结束,延迟多少毫秒之后再收回
        }
    
        @Override
        public void setPrimaryColors(int... colors) {
            setBackgroundColor(getResources().getColor(R.color.activity_bg));
        }
    
        @NonNull
        public View getView() {
            return this;
        }
    
        @Override
        public SpinnerStyle getSpinnerStyle() {
            return SpinnerStyle.Translate;
        }
    
        @Override
        public void onStateChanged(RefreshLayout refreshLayout, RefreshState oldState, RefreshState newState) { // 状态改变事件
            switch (newState) {
                case None: // 无状态
                    if (mCircleProgressView != null) mCircleProgressView.setProgressPersent(0);
                    if (isArrowDown) {
                        arrowAnimation();
                        isArrowDown = false;
                    }
                    break;
                case PullDownToRefresh: // 可以下拉状态
                    mTextView.setText("下拉即可刷新");
                    break;
                case Refreshing: // 刷新中状态
                    mTextView.setText("正在刷新数据...");
                    break;
                case ReleaseToRefresh:  // 释放就开始刷新状态
                    mTextView.setText("松开立即刷新");
                    if (!isArrowDown) {
                        arrowAnimation();
                        isArrowDown = true;
                    }
                    break;
            }
        }
    
        private void arrowAnimation() {
            RotateAnimation ra = new RotateAnimation(0, isArrowDown ? 0 : 180.0f,
                    RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                    RotateAnimation.RELATIVE_TO_SELF, 0.5f);
            ra.setDuration(200);
            ra.setRepeatCount(0);
            ra.setInterpolator(new LinearInterpolator());
            ra.setFillAfter(true);
            mArrow.startAnimation(ra);
        }
    
        /**
         * dp转px
         */
        private int dp2px(Context context, float dpVal) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                    dpVal, context.getResources().getDisplayMetrics());
        }
    }   
    
  5. 创建一个贝塞尔画圆工具CircleProgressView来画圆弧:

    public class CircleProgressView extends View {
        private RectF mRectF;
        private Paint mPaint;
    
        private int width;
        private int height;
        private float persent = 0.0f;  // 进度
        private float lineWidth = 2; // 线宽
    
        public CircleProgressView(Context context) {
            super(context);
            lineWidth = dp2px(context, 1.0f);
            initView();
        }
    
        public CircleProgressView(Context context, AttributeSet attrs) {
            super(context, attrs);
            lineWidth = dp2px(context, 1.0f);
            initView();
        }
    
        @Override
        public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            width = MeasureSpec.getSize(widthMeasureSpec);
            height = MeasureSpec.getSize(heightMeasureSpec);
            if (width != height) {
                int min = Math.min(width, height);
                width = min;
                height = min;
            }
            mRectF.left = lineWidth / 2;
            mRectF.top = lineWidth / 2;
            mRectF.right = width - lineWidth / 2;
            mRectF.bottom = height - lineWidth / 2;
        }
    
        private void initView() {
            mRectF = new RectF();
            mPaint = new Paint();
            mPaint.setAntiAlias(true); 
            mPaint.setColor(getResources().getColor(R.color.theme_color_80));
            mPaint.setStyle(Paint.Style.STROKE);
            mPaint.setStrokeWidth(lineWidth);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
    
            canvas.drawColor(Color.TRANSPARENT);
            canvas.drawArc(mRectF, 90, persent * 350, false, mPaint);
        }
    
        public void setProgressPersent(float persent) {
            this.persent = persent;
            this.invalidate();
        }
    
        // dp转px
        private int dp2px(Context context, float dpVal) {
            return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
                    dpVal, context.getResources().getDisplayMetrics());
        }
    }
    
  6. res\layout\创建一个my_refresh_header.xml文件:

    
    
    
        
    
        
    
            
                
                
            
    
            
        
    
    
    
  7. 使用示例:

    public class MainActivity extends AppCompatActivity {
        private MyRefreshLayout refreshLayout;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            refreshLayout = (MyRefreshLayout)findViewById(R.id.refreshLayout);
            refreshLayout.setOnRefreshListener(new OnRefreshListener() {
                @Override
                public void onRefresh(RefreshLayout refreshlayout) {
                    refreshlayout.finishRefresh(3000); // 模拟请求数据, 3秒后结束
                }
            });
            refreshLayout.setOnLoadmoreListener(new OnLoadmoreListener() {
                @Override
                public void onLoadmore(RefreshLayout refreshlayout) {
                    refreshlayout.finishLoadmore(3000);
                }
            });
        }
    }
    

    xml:

    
    
    
        
    
    
    

你可能感兴趣的:(一个Android下拉刷新样式)