美文网首页
仿带有粘性的圆形刷新控件(2)

仿带有粘性的圆形刷新控件(2)

作者: clam314 | 来源:发表于2017-03-07 13:38 被阅读16次

    实现效果:


    上一篇写了关于图形相关绘制:
    http://www.jianshu.com/p/25aa4789b3fd

    关于动画方面,主要分两个方面:
    一、圆圈拉伸的动画。
    1 、圆被拉出去时的动画
    2、圆拉伸后缩回去的动画
    二、在加载时中心圆弧的动画

    1、圆被拉伸出去时的动画

    首先是记录下手指按下的点的坐标downPoint,然后是手指滑动后停留的点movePoint。并调用invalidate()让view根据两点的状态重新绘制。这样就实现圆随手指滑动而拉伸的动画
    并且在此判断滑动的距离是否触发回滚动画

                case MotionEvent.ACTION_DOWN:
                    if(!stickyAnimator.isRunning() && !loadAnimator.isRunning()){
                        downPoint.x = x;
                        downPoint.y = y;
                        movePoint.set(downPoint);
                        resetLoadAnimator();
                    }
                    break;
                case MotionEvent.ACTION_MOVE:
                    if(!stickyAnimator.isRunning() && !loadAnimator.isRunning() && !loading){
                        movePoint.x = x;
                        movePoint.y = y;
                        float distanceMove = getDistanceBetweenTwoPoints(downPoint.x,downPoint.y,movePoint.x,movePoint.y);
                        //滑动距离在动作范围内,则开始执行回滚动画和loading动画
                        if(inLoadArea(distanceMove)){
                            loading = true;
                            executeAnimator(distanceMove);
                        }
                        invalidate();
                    }
                    break;
    

    2、圆形缩回的动画
    除了在手指滑动距离超过一定范围后触发,在手指离开屏幕时也会触发

                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    if(!stickyAnimator.isRunning() && !loadAnimator.isRunning() && !loading){
                        movePoint.x = x;
                        movePoint.y = y;
                        float distanceUp = getDistanceBetweenTwoPoints(downPoint.x,downPoint.y,movePoint.x,movePoint.y);
                        //滑动距离在动作范围内,则开始执行回滚动画和loading动画,否则只开始回滚动画
                        if(inLoadArea(distanceUp)){
                           loading = true;
                        }
                        executeAnimator(distanceUp);
                    }
                    break;
    

    回滚的动画,其实就是手指最后离开的点movePoint沿着直线移动到当初按下的点downPoin的过程。就是movePoint和downPoin两点的距离distance逐渐变为0的过程,根据distance的变化,可以计算回来movePoint的变化的一系列坐标。按上一篇的介绍,图形的绘制会根据downPoint和movePoint的值来绘制,这样每次movePoint得到新值后,重新绘制就可以实现动画
    初始化的时候就可以设置好动画的参数,StickyAnimator就是负责执行缩回动画的

            //这里先不给animator设置evaluator,因为暂时还不知道需要变化的值,此时设置了也无效
            evaluator = new FloatEvaluator();
            stickyAnimator = new ValueAnimator();
            //设置插值器
            stickyAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
            //设置属性值变化的监听,这里得到的newDistance就是两点新的距离
            stickyAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float newDistance = (float) animation.getAnimatedValue();
                    float distance = getDistanceBetweenTwoPoints(downPoint.x,downPoint.y,movePoint.x,movePoint.y);
                    float cos = (movePoint.x - downPoint.x)/distance;
                    float sin = (movePoint.y - downPoint.y)/distance;
                    movePoint.x = downPoint.x + newDistance * cos;
                    movePoint.y = downPoint.y + newDistance * sin;
                    invalidate();
                }
            });
            //圆形缩回来后判断是否需要执行loading动画
            stickyAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    //在onTouchEvent里面判断了移动的距离是否触发加载动画
                    if(loading){
                        loadAnimator.start();
                        if(mReloadListener != null) mReloadListener.onReload();
                    }
                }
            });
    

    在onTouchEvent()方法里面判断执行的时机,并且获取动画需要变化的值

    private boolean inLoadArea(float distance){
            return distance <= MaxMoveDistance*0.75 && distance >= MaxMoveDistance * 0.33;
        }
    
    private void executeAnimator(float distance){
            //两个圆重合时无需回滚
            if(distance == 0) return;
            stickyAnimator.setObjectValues(distance,0);
            stickyAnimator.setEvaluator(evaluator);
            stickyAnimator.setDuration(STICKY_DURATION);
            stickyAnimator.start();
        }
    

    3、加载动画的实现
    触发加载动画后,mLoadAnimatorValue的值由0到1,然后再绘制的时候根据这个值计算出截取圆弧的部分

            loadAnimator = ValueAnimator.ofFloat(0,1).setDuration(LOADING_DURATION);
            loadAnimator.setRepeatCount(-1);//loading动画一直执行,直到调用cancel()后才停止
            loadAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    mLoadAnimatorValue = (float) animation.getAnimatedValue();
                    invalidate();
                }
            });
    
        private void drawLoading(Canvas canvas){
            //基本和绘制一般状态的时候一样,除了截取的起点和终点需要动态的计算
            canvas.save();
            canvas.translate(circleStart.centerPoint.x, circleStart.centerPoint.y);
            canvas.scale(1 - mScale,1 - mScale);
            pathMeasure.setPath(mLoadPath,false);
            Path newPath = new Path();
            float stop = pathMeasure.getLength() * mLoadAnimatorValue;
            float start = (float)(stop - (0.5 - Math.abs(mLoadAnimatorValue - 0.5)) * 200f);
            pathMeasure.getSegment(start,stop,newPath,true);
            canvas.drawPath(newPath, mLoadPaint);
            canvas.restore();
        }
    

    当loading动画会一直执行直到调用cancel()方法才停止。当所有动画都停止后,在手指按下屏幕的时候,重置一下状态

                case MotionEvent.ACTION_DOWN:
                    if(!stickyAnimator.isRunning() && !loadAnimator.isRunning()){
                        downPoint.x = x;
                        downPoint.y = y;
                        movePoint.set(downPoint);
                        resetLoadAnimator();
                    }
                    break;
    

    项目地址:https://github.com/clam314/StickyCircleView

    相关文章

      网友评论

          本文标题:仿带有粘性的圆形刷新控件(2)

          本文链接:https://www.haomeiwen.com/subject/hnxmgttx.html