[Android开发]仿带有粘性的圆形刷新控件(2)

实现效果:


上一篇写了关于图形相关绘制:
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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容