04.Android之动画问题

2次阅读

共计 5868 个字符,预计需要花费 15 分钟才能阅读完成。

目录介绍

4.0.0.1 Android 中有哪几种类型的动画,属性动画和补间动画有何区别?补间动画和属性动画常用的有哪些?
4.0.0.2 View 动画为何不能真正改变 View 的位置?而属性动画为何可以?属性动画是如何改变 View 的属性?
4.0.0.3 补间动画是如何作用于 view 的,从源码角度分析以下?为何说补间动画没有改变 View 的属性?
4.0.0.6 属性动画插值器和估值器的作用?插值器和估值器分别是如何更改动画的?
4.0.0.7 使用动画会出现哪些问题?动画占用大量内存,如何优化?使用动画的注意事项有哪些?

好消息

博客笔记大汇总【15 年 10 月到至今】,包括 Java 基础及深入知识点,Android 技术博客,Python 学习笔记等等,还包括平时开发中遇到的 bug 汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是 markdown 格式的!同时也开源了生活博客,从 12 年起,积累共计 500 篇 [近 100 万字],将会陆续发表到网上,转载请注明出处,谢谢!
链接地址:https://github.com/yangchong2…
如果觉得好,可以 star 一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!所有的笔记将会更新到 GitHub 上,同时保持更新,欢迎同行提出或者 push 不同的看法或者笔记!

4.0.0.1 Android 中有哪几种类型的动画,属性动画和补间动画有何区别?

常见三类动画

View 动画(View Animation)/ 补间动画(Tween animation):对 View 进行平移、缩放、旋转和透明度变化的动画,不能真正的改变 view 的位置。应用如布局动画、Activity 切换动画
逐帧动画(Drawable Animation):是 View 动画的一种,它会按照顺序播放一组预先定义好的图片
属性动画(Property Animation):对该类对象进行动画操作,真正改变了对象的属性

属性动画和补间动画区别

属性动画才是真正的实现了 view 的移动,补间动画对 view 的移动更像是在不同地方绘制了一个影子,实际对象还是处于原来的地方。当动画的 repeatCount 设置为无限循环时,如果在 Activity 退出时没有及时将动画停止,属性动画会导致 Activity 无法释放而导致内存泄漏,而补间动画却没问题。xml 文件实现的补间动画,复用率极高。在 Activity 切换,窗口弹出时等情景中有着很好的效果。
补间动画还有一个致命的缺陷,就是它只是改变了 View 的显示效果而已,而不会真正去改变 View 的属性。什么意思呢?比如说,现在屏幕的左上角有一个按钮,然后我们通过补间动画将它移动到了屏幕的右下角,现在你可以去尝试点击一下这个按钮,点击事件是绝对不会触发的,因为实际上这个按钮还是停留在屏幕的左上角,只不过补间动画将这个按钮绘制到了屏幕的右下角而已。下面这张图摘自网络!

补间动画和帧动画 xml 文件存放的位置

补间动画是放置到 res/anim/ 下面
帧动画是放置到 res/drawable/ 下面,子节点为 animation-list,在这里定义要显示的图片和每张图片的显示时长

补间动画和属性动画常用的有哪些?技术博客大总结

View 动画框架是旧的框架,只能用于 Views。比较容易设置和能满足许多应用程序的需要。View 动画框架中一共提供了 AlphaAnimation(透明度动画)、RotateAnimation(旋转动画)、ScaleAnimation(缩放动画)、TranslateAnimation(平移动画)四种类型的补间动画;并且 View 动画框架还提供了动画集合类(AnimationSet),通过动画集合类(AnimationSet)可以将多个补间动画以组合的形式显示出来。
与属性动画相比 View 动画存在一个缺陷,View 动画改变的只是 View 的显示,而没有改变 View 的响应区域,并且 View 动画只能对 View 做四种类型的补间动画。因此 Google 在 Android3.0(API 级别 11)及其后续版本中添加了属性动画框架,从名称中就可以知道只要某个类具有属性(即该类含有某个字段的 set 和 get 方法),那么属性动画框架就可以对该类的对象进行动画操作(其实就是通过反射技术来获取和执行属性的 get,set 方法),同样属性动画框架还提供了动画集合类(AnimatorSet),通过动画集合类(AnimatorSet)可以将多个属性动画以组合的形式显示出来。

4.0.0.2 View 动画为何不能真正改变 View 的位置?而属性动画为何可以?属性动画是如何改变 View 的属性?

View 动画为何不能真正改变 View 的位置?而属性动画为何可以?

View 动画改变的只是 View 的显示,而没有改变 View 的响应区域;而属性动画会通过反射技术来获取和执行属性的 get、set 方法,从而改变了对象位置的属性值。
Animation 产生的动画数据实际并不是应用在 View 本身的,而是应用在 RenderNode 或者 Canvas 上的,这就是为什么 Animation 不会改变 View 的属性的根本所在。

属性动画是如何改变 View 的属性?
具体看我这篇博客:https://www.jianshu.com/p/4af…

4.0.0.3 补间动画是如何作用于 view 的,从源码角度分析以下?为何说补间动画没有改变 View 的属性?

关于补间动画原理

要了解 Android 动画是如何加载出来的, 我们首先要了解 Android View 是如何组织在一起的. 每个窗口是一颗 View 树. RootView 是 DecorView, 在布局文件中声明的布局都是 DecorView 的子 View. 是通过 setContentView 来设置进入窗口内容的. 因为 View 的布局就是一棵树. 所以绘制的时候也是按照树形结构来遍历每个 View 进行绘制.ViewRoot.java 中 draw 函数准备好 Canvas 后 调用 mView.draw(canvas), 这里的 mView 是 DecorView.

下面看一下递归绘制的几个步骤: 技术博客大总结

1. 绘制背景
2. 如果需要, 保存画布 (canvas), 为淡入淡出做准备
3. 通过调用 View.onDraw(canvas) 绘制 View 本身的内容
4. 通过 dispatchDraw(canvas) 绘制自己的孩子,dispatchDraw->drawChild->child.draw(canvas) 这样的调用过程被用来保证每个子 View 的 draw 函数都被调用
5. 如果需要,绘制淡入淡出相关的内容并恢复保存的画布所在的层(layer)
6. 绘制修饰的内容(例如滚动条)
当一个 ChildView 要重画时,它会调用其成员函数 invalidate() 函数将通知其 ParentView 这个 ChildView 要重画,这个过程一直向上遍历到 ViewRoot,当 ViewRoot 收到这个通知后就会调用上面提到的 ViewRoot 中的 draw 函数从而完成绘制。Android 动画就是通过 ParentView 来不断调整 ChildView 的画布坐标系来实现的

如何计算补间动画数据

首先进入 Animation 类,然后找到 getTransformation 方法,主要是分析这个方法逻辑,如图所示

那么这个方法中做了什么呢?Animation 在其 getTransformation 函数被调用时会计算一帧动画数据,而上面这些属性基本都是在计算动画数据时有相关的作用。
第一步:若 startTime 为 START_ON_FIRST_FRAME(值为 -1) 时,将 startTime 设定为 curTime

第二步:计算当前动画进度:

normalizedTime = (curTime – (startTime + startOffset))/duration
若 mFillEnabled==false:将 normalisedTime 夹逼至 [0.0f, 1.0f]

第三步:判断是否需要计算动画数据:

若 normalisedTime 在 [0.0f, 1.0f],需计算动画数据

若 normalisedTime 不在 [0.0f, 1.0f]:

normalisedTime<0.0f, 仅当 mFillBefore==true 时才计算动画数据
normalisedTime>1.0f, 仅当 mFillAfter==true 时才计算动画数据

第四步:若需需要计算动画数据:

若当前为第一帧动画,触发 mListener.onAnimationStart
若 mFillEnabled==false:将 normalisedTime 夹逼至 [0.0f, 1.0f]
根据插间器 mInterpolator 调整动画进度:
interpolatedTime = mInterpolator.getInterpolation(normalizedTime)
若动画反转标志位 mCycleFlip 为 true,则
interpolatedTime = 1.0 – normalizedTime
调用动画更新函数 applyTransformation(interpolatedTime, transformation) 计算出动画数据

第五步:若夹逼之前 normalisedTime 大于 1.0f, 则判断是否需继续执行动画:

已执行次数 mRepeatCount 等于需执行次数 mRepeated
若未触发 mListener.onAnimationEnd,则触发之

已执行次数 mRepeatCount 不等于需执行次数 mRepeated 技术博客大总结

自增 mRepeatCount
重置 mStartTime 为 -1
若 mRepeatMode 为 REVERSE,则取反 mCycleFlip
触发 mListener.onAnimationRepeat

4.0.0.6 属性动画插值器和估值器的作用?插值器和估值器分别是如何更改动画的?

插值器 (Interpolator):根据时间流逝的百分比计算出当前属性值改变的百分比。确定了动画效果变化的模式,如匀速变化、加速变化等等。View 动画和属性动画均可使用。常用的系统内置插值器:

线性插值器 (LinearInterpolator):匀速动画
加速减速插值器 (AccelerateDecelerateInterpolator):动画两头慢中间快
减速插值器 (DecelerateInterpolator):动画越来越慢

类型估值器 (TypeEvaluator):根据当前属性改变的百分比计算出改变后的属性值。针对于属性动画,View 动画不需要类型估值器。常用的系统内置的估值器:技术博客大总结

整形估值器 (IntEvaluator)
浮点型估值器 (FloatEvaluator)
Color 属性估值器 (ArgbEvaluator)

4.0.0.7 使用动画会出现哪些问题?动画占用大量内存,如何优化?使用动画的注意事项有哪些?

使用动画会出现哪些问题?

OOM 问题:这个问题主要出现在帧动画中,当图片数量较多且图片较大时就极易出现 OOM,这个在实际开发中要尤其注意,尽量避免使用帧动画。
内存泄露:在属性动画中有一类无限循环的动画,这类动画需要在 Activity 退出时及时停止,否则将导致 Activity 无法释放从而造成内存泄露,通过验证后发现 View 动画并不存在此问题。

动画占用大量内存,如何优化?

使用动画的注意事项有哪些?

OOM 问题:这个问题主要出现在帧动画中,当图片数量较多且图片较大时就极易出现 OOM,这个在实际开发中要尤其注意,尽量避免使用帧动画。
内存泄露:在属性动画中有一类无限循环的动画,这类动画需要在 Activity 退出时及时停止,否则将导致 Activity 无法释放从而造成内存泄露,通过验证后发现 View 动画并不存在此问题。
兼容性问题:动画在 3.0 以下的系统有兼容性问题,在某些特殊场景可能无法正常工作,因此要做好适配工作。
View 动画的问题:View 动画是对 View 的影像做动画,并不是真正改变 View 的状态,因此有时候会出现动画完成后 View 无法隐藏的现象,即 setVisibility(View.GOEN) 失效了,这个时候只要调用 view.clearAnimation() 清除 View 动画即可解决问题。技术博客大总结

不要使用 px:在进行动画的过程中,要尽量使用 dp,使用 px 会导致在不用的设备上有不用的效果。
动画元素的交互:从 3.0 开始,将 view 移动(平移)后,属性动画的单击事件触发位置为移动后的位置,但是 View 动画仍然在原位置。在 Android3.0 以前的系统中,不管是 View 动画还是属性动画,新位置都无法触发单击事件同时,老位置仍然能触发单击事件(因为属性动画在 Android3.0 以前是没有的,是通过兼容包实现的,底层也是调用 View 动画)。
硬件加速:使用动画的过程中,建议开启硬件加速,这样会提高动画的流畅性。
开启方法:
在你的 Android manifest 文件,添加 hardwareAccelerated 属性就可以了。可以给整个 application 添加,也可以单独给一个 acitivty 添加,该属性默认值为 false;

关于其他内容介绍
01. 关于博客汇总链接

1. 技术博客汇总

2. 开源项目汇总

3. 生活博客汇总

4. 喜马拉雅音频汇总

5. 其他汇总

02. 关于我的博客

我的个人站点:www.yczbj.org,www.ycbjie.cn
github:https://github.com/yangchong211

知乎:https://www.zhihu.com/people/…

简书:http://www.jianshu.com/u/b7b2…

csdn:http://my.csdn.net/m0_37700275

喜马拉雅听书:http://www.ximalaya.com/zhubo…

开源中国:https://my.oschina.net/zbj161…

泡在网上的日子:http://www.jcodecraeer.com/me…

邮箱:yangchong211@163.com
阿里云博客:https://yq.aliyun.com/users/a… 239.headeruserinfo.3.dT4bcV
segmentfault 头条:https://segmentfault.com/u/xi…

掘金:https://juejin.im/user/593943…

正文完
 0