手把手教你绘制Android粘性果冻动画组件

        从事移动互联网开发已经快两年了,回想当初是Android带我走进了移动端的世界,后来由于自身对用户体验比较感兴趣,发现iOS更注重对图形渲染以及动画处理,所以转身自学iOS开发,之后也发布了几个iOS的组件库。但是Android进两年发展趋势猛增,在动画处理上也比以前有所改进,Android3.0之后开启了GPU硬件加速让图形渲染没以前那么卡顿,特别是5.0之后的material design更是引领潮流。所以趁最近工作不忙有时间,写了个弹性动画的ActionMenu,核心原理来自咱们iOS界有动画小王子之称的kittenyang的这篇博客(特此鸣谢),废话不多说了,先上效果图(gif存在失真,实际效果更佳流畅Q弹)

SpringActionMenu效果图

1.核心原理

        主要知识点其实就下面三项

        * Android自定义View以及ViewGroup

        * 利用三阶贝塞尔曲线绘制图形

        * 通过ValueAnimator结合阻尼振动自定义属性变化

2.各项讲解

(1)Android自定义View以及ViewGroup

        首先我们先做出一个圆形的弹性动画效果,先得自定义一个view,然后重写onDraw可以用过path和paint任意绘制图形,具体细节我就不多说了,不了解的同学可以查阅相关资料学习。

(2)利用三阶贝塞尔曲线绘制图形

        贝塞尔曲线是我认为一个比较神奇的东西,因为他基本上可以绘制出任何图形,有兴趣的同学可以到这个网站玩一下,那么我们今天需要做的就是用三阶贝塞尔曲线画圆

三阶贝塞尔曲线画圆

图中以A,B,C,D四个点作为基准点,把一个圆分4次绘制,以c1-c8作为四次绘制中三阶贝塞尔曲线的辅助点,各点的位置我们设为offSet,由前辈们计算,当offSet为(圆形直径/3.6)时刚好是一个整圆,后来找到一篇文章介绍了其原理(虽然我看完之后还是一脸懵逼)。我们设置形变系数为factor(0~1),设定圆形拉伸的最大程度为圆形的2/5, 则extra= circleRadius*2*factor/5,分别列出各点坐标

intxA =0,xB =0,xC =0,xD =0,yA =0,yB =0,yC =0,yD =0;

xA =circleRadius;

xB =circleRadius*2+extra;

xC =circleRadius;

xD =0;

yA =extra;

yB =circleRadius;

yC =circleRadius*2-extra;

yD =circleRadius;

offSet=circleRadius*2/3.6f;

mPath.moveTo(xA,yA);

mPath.cubicTo(xA +offSet,yA,xB,yB  -offSet,xB,yB);

mPath.cubicTo(xB,yB +offSet,xC +offSet,yC,xC,yC);

mPath.cubicTo(xC -offSet,yC,xD,yD  +offSet,xD,yD);

mPath.cubicTo(xD,yD -offSet,xA -offSet,yA,xA,yA);

OK!基本点都绘制完了,直接Run起来


绘制圆形

看到一个红通通的圆形绘制成功之后第一部大功告成!

(3)通过ValueAnimator结合阻尼振动自定义属性变化

        上面我们已经绘制好了一个圆形,接下来事情就很简单了,只需要通过改变形变系数factor(0~1)的值来改变形变程度就可以了,下面介绍一个Android的动画API—ValueAnimator,直接通过组件属性定义的动画效果,然后重写变化机制

ValueAnimator valueAnimator = ValueAnimator.ofObject(new FloatEvaluator(time,1,0),1,0);

valueAnimator.addUpdateListener(this);

valueAnimator.setDuration(time);

valueAnimator.start();

@Override

public voidonAnimationUpdate(ValueAnimator animation) {

      factor= (float)animation.getAnimatedValue();

      invalidate();

}

由此原理就是通过属性动画不断的改变factor从1到0,然后刷新重绘小圆球,FloatEvaluator就是我们自定义的根据什么样的函数去改变factor,这个时候就要介绍到我们高中学习的阻尼振动函数了

阻尼振动


阻尼振动

该函数可以模拟最真实的弹性效果

阻尼振动函数

我们60帧为基准(肉眼看到刷新流畅度的最低标准),计算出一列变化factor的值

publicFloatEvaluator(longtime, floatstartValue, floatendValue) {

        sum= (int)time *60/1000;

        float diff = endValue - startValue;

        value=new float[sum];

        float x;

        for(int i = 0; i < sum; i++) {

        x = i *1.0f/sum;

        value[i] = endValue - (float)(diff * Math.pow(Math.E,-1*dampingFactor* x) * Math.cos(velocityFactor* x));

        }

}

其中dampingFactor和velocityFactor为阻力和速度,我这里设置的是5和30,可以自定义调节改变弹性程度。

基本构建完成,添加一个按钮启动动画试试效果


弹性动画效果图

大功告成!

3.总结

        大家掌握了一个圆形组件的形变原理之后剩下的就容易多了,利用ViewGroup多绘制几个摆摆位置就OK了,也可以利用这种原理自己创新构思出别的控件,只要掌握了核心的两点:

        1.贝塞尔曲线绘制图形

        2.利用阻尼函数以及ValueAnimator自定义形变属性的值

        最后贴上源码地址,有兴趣的同学欢迎star,共同学习探讨动画知识!

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

推荐阅读更多精彩内容

  • 1 背景 不能只分析源码呀,分析的同时也要整理归纳基础知识,刚好有人微博私信让全面说说Android的动画,所以今...
    未聞椛洺阅读 2,577评论 0 9
  • 作为备用知识,memo 学过矩阵理论或者线性代数的肯定知道正交矩阵(orthogonal matrix)是一个非常...
    HappyPieBinLiu阅读 5,552评论 0 5
  • 转载一篇高质量博文,原地址请戳这里转载下来方便今后查看。1 背景不能只分析源码呀,分析的同时也要整理归纳基础知识,...
    Elder阅读 1,898评论 0 24
  • 在微博上搜“和陌生人打电话” 出现的的是“和陌生人打电话说什么” “和陌生人打电话太可怕了!”…… 但是小年青我呢...
    杏杏酱阅读 1,558评论 1 1
  • 1、虚拟机在选择开启此虚拟机弹出内部错误。答:在虚拟机图标上,右键选择以管理员身份运行,就可以解决了。 2、Win...
    笑笑学生阅读 532评论 0 0