当前位置: 首页 > news >正文

PhysicsBasedAnimation学习

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

概述

Google I/O ‘17推出了许多新的特性,在动画这一块又有新的API供开发者使用,具体视频请见Android Animations Spring to Life (Google I/O ‘17),主要介绍了Physics-based Animations,在动画API中引入了DynamicAnimation,并介绍了它的两个子类FlingAnimationSpringAnimation的使用,开发者可以使用新的API创建更加动态化的动画。

是什么

Physics-based Animations,翻译过来就是基于物理的动画,官网上有很详细的介绍,在日常生活中当一个事物发生变化的时候,物理性的过渡或者说符合自然性的过渡,更容易让我们感知察觉,同样,更自然、不间断、有良好发展趋势的动画会给我们带来更好的用户体验。Physics-based Animations是根据物理学的基本原理构建的动画,动画由力产生,当力趋于平衡时动画处于静止。让我们重新捡起高中半吊子水平的物理知识,比如给物体在某个方向上施加一个力,物体有了速度,会在该方向上运动,如果停止施力,最后物体会由于摩擦力的影响,速度逐渐减小,运动一段时间后处于静止状态。Physics-based Animations概括起来就是下面几点:

  • 动画由力驱动
  • 力决定了动画的加速和减速
  • 在每一帧中动画值和速度都会更新
  • 当受力达到平衡时动画停止

好处

使用Physics-based Animations api创建的动画可以追踪速度,在运动过程中动态地改变动画的目标值,正确规划路线,使动画看起来更加自然。看下两组动画

​ targetchange_oa.gif

targetchange_pba.gif

对比了两组动画的差别,图1动画无法追踪速度,在进行下一帧的时候它的速度几乎还是从0开始的,速度值突然的变化给用户不连贯的视觉体验。图2动画可以追踪速度,在第二阶段力的方向改变,导致原先的速度发生变化,图片看起来很自然地移动到新的位置

动画1的速度曲线图动画1的速度曲线图
动画2的速度曲线图动画2的速度曲线图

怎么用

  • Android Studio 3.0 Canary 4
  • 在Android Studio的build.gradle中添加依赖
 

1

2

3

4

 

dependencies {

...

implementation 'com.android.support:support-dynamic-animation:26.0.0-beta2'

}

Fling Animation

看下怎样创建FlingAnimation:

 

1

2

3

4

5

 

ImageView img = root.findViewById(R.id.img_simple_fling);

FlingAnimation flingAnimation = new FlingAnimation(img, DynamicAnimation.X);

flingAnimation.setStartVelocity(500f);

flingAnimation.setFriction(0.5f);

flingAnimation.start();

效果如下:

fling.gif

解释下上面的代码:
创建一个FlingAnimation实例,默认情况下该实例的初速度是0pixels/s,因此我们需要调用setStartVelocity()方法给它赋予一个大于0的初速度,否则它是不会动的;另外这里介绍下Friction,翻译过来就是摩擦力的意思,在现实生活中如果一个物体保持一个速度在无摩擦力的情况下会一直运动下去,这里也是(比如这里设置Fraction为0.01f,发现小球滚到屏幕外了),我们需要给该实例设置一个摩擦系数,设置的值越大,说明摩擦力越大,动画越快停下来,默认该值为1;最后调用start()方法开始动画。

Spring Animation

看下怎样创建SpringAnimation:

 

1

2

3

4

5

6

7

8

9

10

11

 

ImageView img = root.findViewById(R.id.img_simple_spring);

SpringAnimation springAnimation = new SpringAnimation(img, DynamicAnimation.X);

springAnimation.setStartVelocity(2000);

SpringForce springForce = new SpringForce();

springForce.setDampingRatio(SpringForce.DAMPING_RATIO_HIGH_BOUNCY);

springForce.setStiffness(SpringForce.STIFFNESS_LOW);

springForce.setFinalPosition(img.getX());

springAnimation.setSpring(springForce);

springAnimation.start();

效果如下:

spring.gif

解释下上面的代码:
和FlingAnimation一样,创建完SpringAnimation后我们需要设置初速度,接着创建了一个
SpringForce实例,并设置了DampingRatio(弹性阻尼)和Stiffness(生硬度),
DampingRatio可以理解成反弹次数,系统中有以下几个可选,

 

1

2

3

4

 

public static final float DAMPING_RATIO_HIGH_BOUNCY = 0.2F;

public static final float DAMPING_RATIO_MEDIUM_BOUNCY = 0.5F;

public static final float DAMPING_RATIO_LOW_BOUNCY = 0.75F;

public static final float DAMPING_RATIO_NO_BOUNCY = 1.0F;

默认设置为DAMPING_RATIO_MEDIUM_BOUNCY,在官网上贴了四张很Q弹的图片,分别对应不同值的效果,该值越大,反弹次数越少,值为1时不反弹。
Stiffness可以理解成要恢复成未拉伸状态所需的时间,系统中有以下几个可选,

 

1

2

3

4

 

public static final float STIFFNESS_HIGH = 10000.0F;

public static final float STIFFNESS_MEDIUM = 1500.0F;

public static final float STIFFNESS_LOW = 200.0F;

public static final float STIFFNESS_VERY_LOW = 50.0F;

默认设置为STIFFNESS_MEDIUM,在官网同样贴了四张对应不同值得对比图,该值越大,恢复到之前状态的时间就越短。可以修改DampingRatioStiffness查看效果

physics2.gif

setFinalPosition()方法指定最后静止时的位置。

创建自定义的动画属性

SpringAniamtion和FlingAnimation的构造函数只能接收一个可动画属性参数,如ALPHAROTATIONSCALE等,如果要同时为多个属性生成动画,一种方法是创建多个对应类的实例,然后传入要改变的动画值,这种做法比较麻烦,我们可以创建一个新的属性,该属性封装了我们想改变的其他动画属性值,做法如下:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

 

FloatPropertyCompat<View> scale =

new FloatPropertyCompat<View>("scale") {

@Override

public float getValue(View view) {

// return the value of any one property

return view.getScaleX();

}

@Override

public void setValue(View view, float value) {

// Apply the same value to two properties

view.setScaleX(value);

view.setScaleY(value);

}

};

创建FloatPropertyCompat实例,在setValue()方法中更新要修改的动画属性,在getValue()方法中返回当前属性值,示例代码统一改变了SCALE_XSCALE_Y属性,自定义属性创建好之后可以像其他动画属性一样使用它,

 

1

2

 

SpringAnimation stretchAnimation =

new SpringAnimation(emoji, scale);

在创建使用自定义属性的动画时,最好也调用setMinimumVisibleChange()方法并传递一个有意义的值,以确保动画不会消耗太多的CPU性能

 

1

2

 

stretchAnimation.setMinimumVisibleChange(

DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE);

效果如下:

stretch.gif

动画监听

DynamicAnimation提供了两个动画监听器OnAnimationUpdateListener和 OnAnimationEndListener,从名字也可以猜到前者监听动画值改变,后者监听动画结束状态。添加动画变化监听需要调用addUpdateListener()方法,重写onAnimationUpdate()方法执行具体操作;添加动画结束监听需要调用addEndListener()方法,重写onAnimationEnd()方法执行具体操作;若要移除动画监听,则需要调用removeUpdateListener()removeEndListener()。监听动画结束的使用场景:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

 

// Change icon before animation starts

emoji.setImageResource(

R.drawable.ic_sentiment_very_satisfied_black_56dp);

// Start animation

springAnimation.start();

springAnimation.addEndListener(

new DynamicAnimation.OnAnimationEndListener() {

@Override

public void onAnimationEnd(DynamicAnimation animation,

boolean canceled,

float value, float velocity) {

// Change icon after animation ends

emoji.setImageResource(

R.drawable.ic_sentiment_neutral_black_56dp);

}

});

当动画结束时变换表情,效果如下:

bounce.gif

监听动画变化的使用场景:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

 

// Creating two views to demonstrate the registration of the update listener.

final View view1 = findViewById(R.id.view1);

final View view2 = findViewById(R.id.view2);

// Setting up a spring animation to animate the view1 and view2 translationX and translationY properties

final SpringAnimation anim1X = new SpringAnimation(view1,

DynamicAnimation.TRANSLATION_X);

final SpringAnimation anim1Y = new SpringAnimation(view1,

DynamicAnimation.TRANSLATION_Y);

final SpringAnimation anim2X = new SpringAnimation(view2,

DynamicAnimation.TRANSLATION_X);

final SpringAnimation anim2Y = new SpringAnimation(view2,

DynamicAnimation.TRANSLATION_Y);

// Registering the update listener

anim1X.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() {

// Overriding the method to notify view2 about the change in the view1’s property.

@Override

public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value,

float velocity) {

anim2X.animateToFinalPosition(value);

}

});

anim1Y.addUpdateListener(new DynamicAnimation.OnAnimationUpdateListener() {

@Override

public void onAnimationUpdate(DynamicAnimation dynamicAnimation, float value,

float velocity) {

anim2Y.animateToFinalPosition(value);

}

});

我们可以结合animateToFinalPosition()方法实现链式弹力动画效果,即一个View的动画依赖于另一个,效果如下:

spring_chain.gif

Thanks to

  • Adding Physics-Based Animations to Android Apps
  • Physics-based Animations
  • Spring Animation
  • Fling Animation
  • 官方Demo

GitHub Demo传送门

转载于:https://my.oschina.net/JiangTun/blog/1621148

相关文章:

  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • Mybatis分页插件PageHelper简单使用
  • 企业IM-2技术选型
  • 干货分享微服务spring-cloud(1.初探)
  • java 内存溢出 栈溢出的原因与排查方法
  • Qpid第四课 异常以及崩溃
  • [杂记]CodeBlocks下载、安装及设置
  • 马哥教育M28第十三天到第十五天学习总结
  • centos查找命令介绍
  • jp@gc - Stepping Thread Group配置解释描述
  • 如何在cowboy应用中指定mnesia数据库路径
  • underscore 的debounce
  • Maven项目pom.xml文件简单解析
  • 菜鸟学Python之django-simple-captcha使用
  • Swift Collection 中的 lazy 作用
  • 分享一款快速APP功能测试工具
  • 【跃迁之路】【641天】程序员高效学习方法论探索系列(实验阶段398-2018.11.14)...
  • android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码...
  • Android优雅地处理按钮重复点击
  • canvas 高仿 Apple Watch 表盘
  • es6--symbol
  • Js基础知识(四) - js运行原理与机制
  • js中forEach回调同异步问题
  • Netty 4.1 源代码学习:线程模型
  • OSS Web直传 (文件图片)
  • Xmanager 远程桌面 CentOS 7
  • 第2章 网络文档
  • 高性能JavaScript阅读简记(三)
  • 入手阿里云新服务器的部署NODE
  • 使用 @font-face
  • 提醒我喝水chrome插件开发指南
  • 我看到的前端
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • const的用法,特别是用在函数前面与后面的区别
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • ​卜东波研究员:高观点下的少儿计算思维
  • ​猴子吃桃问题:每天都吃了前一天剩下的一半多一个。
  • # 数据结构
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • #QT(串口助手-界面)
  • #传输# #传输数据判断#
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • (第一天)包装对象、作用域、创建对象
  • (附源码)springboot 智能停车场系统 毕业设计065415
  • (免费领源码)python+django+mysql线上兼职平台系统83320-计算机毕业设计项目选题推荐
  • (十一)c52学习之旅-动态数码管
  • (续)使用Django搭建一个完整的项目(Centos7+Nginx)
  • (一)插入排序
  • (转)淘淘商城系列——使用Spring来管理Redis单机版和集群版
  • (转载)PyTorch代码规范最佳实践和样式指南
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET 6 Mysql Canal (CDC 增量同步,捕获变更数据) 案例版
  • .net mvc部分视图
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .NET框架设计—常被忽视的C#设计技巧