Learn && Live

虚度年华浮萍于世,勤学善思至死不渝

前言

Hey,欢迎阅读Connor学Android系列,这个系列记录了我的Android原理知识学习、复盘过程,欢迎各位大佬阅读斧正!原创不易,转载请注明出处:http://t.csdn.cn/2kSSX,话不多说我们马上开始!

Android动画可以分为三种:View动画、帧动画和属性动画

  • View动画:通过对场景里的对象不断做图像变换(平移、缩放、旋转、透明度)从而产生动画效果,且支持自定义
  • 帧动画:通过顺序播放一系列图像从而产生动画效果。可以简单理解为图片切换动画,如果图片过多过大会导致OOM
  • 属性动画:通过动态改变对象的属性从而达到动画效果

7.1 View动画

View动画对应四种动画效果:平移动画、缩放动画、旋转动画和透明度动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"android:interpolator="@android:anim/accelerate_decelerate_interpolator"><scaleandroid:duration="3000"android:fromXScale="0.0"android:fromYScale="0.0"android:pivotX="50%"android:pivotY="50%"android:toXScale="1.0"android:toYScale="1.0"/><alphaandroid:duration="3000"android:fromAlpha="1.0"android:toAlpha="0.5" /><rotateandroid:fromDegrees="0"android:toDegrees="720"android:pivotX = "50%"android:pivotY="50%"android:duration = "3000"/><translateandroid:fromXDelta="0"android:toXDelta="100"android:fromYDelta="0"android:toYDelta="100" />
</set>

<set> 标签表示动画集合,对应 AnimationSet 类,可以包含若干个动画,且内部可以嵌套其他动画集合

  • android:interpolator:表示动画集合的插值器,可以影响动画的速度
  • android:shareInterpolator:表示集合中的动画是否和集合共享插值器。如果集合不指定插值器,则子动画需要单独指定插值器或使用默认值

1.平移动画

<translate> 表示平移动画,对应 TranslateAnimation 类,可以使一个View在水平和竖直方向完成平移的动画效果

  • android;fromXDelta:表示x的起始值
  • android:toXDelta:表示x的结束值
  • android:fromYDelta:表示y的起始值
  • android:toYDelta:表示y的结束值

2.缩放动画

<scale> 表示缩放动画,对应 ScaleAnimation 类,可以使View具有放大或缩小的动画效果

  • android:fromXScale:水平方向缩放的起始值
  • android:toXScale:水平方向缩放的结束值
  • android:fromYScale:竖直方向缩放的起始值
  • android:toYScale:竖直方向缩放的结束值
  • android:pivotX:缩放轴点的x坐标
  • android:pivotY:缩放轴点的y坐标

默认情况下轴点是View的中心点,此时在水平方向上缩放会导致View向左右两个方向同时缩放,但是如果把轴点设为View的右边界,那么View就只会向左边进行缩放,反之则向右边进行缩放

3.旋转动画

<rotate> 表示旋转动画,对应 RotateAnimation 类,可以使View具有旋转的动画效果

  • android:fromDegrees:旋转开始的角度
  • android:toDegrees:旋转结束的角度
  • android:pivotX:旋转轴点的x坐标
  • android:pivotY:旋转轴点的y坐标

默认情况下轴点是View的中心点

4.透明度动画

<alpha> 表示透明度动画,对应 AlphaAnimation 类,可以改变View的透明度

  • android:fromAlpha:透明度的起始值
  • android:toAlpha:透明度的结束值

5.其他属性

  • android:duration:动画持续时间
  • android:fillAfter:动画结束后是否停留在结束位置

6.使用动画

定义动画,可以通过XML定义也可以在代码中动态定义

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"android:interpolator="@android:anim/accelerate_decelerate_interpolator"><rotateandroid:fromDegrees="0"android:toDegrees="90"android:duration = "400" /><translateandroidLduration="100"android:fromXDelta="0"android:fromYDelta="0"android:interpolator="@android:anim/linear_interpolator"android:toXDelta="100"android:toYDelta="100" />
</set>Button mButton = findViewById(R.id.button1);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.animationtest);
mButton.startAnimation(animation);
AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);
alphaAnimation.setDuration(300);
mButton.startAnimation(alphaAnimation);

7.自定义View动画

(1)继承抽象类Animation

(2)重写initialize和applyTransformation方法,在initialize方法中做一些初始化工作,在applyTransformation中进行相应的矩阵变换即可

8.View动画的特殊使用场景

LayoutAnimation

作用于ViewGroup,为ViewGroup指定一个动画,在其子元素显示时会具有该动画效果。使用步骤如下:

(1)定义为子元素指定的具体的动画

// res/anim/anim_item.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"android:duration="300"android:interpolator="@android:anim/accelerate_decelerate_interpolator"android:shareInterpolator="true"><alphaandroid:fromAlpha="0.0"android:toAlpha="1.0" /><translateandroid:fromXDelta="500"android:toXDelta="0" />
</set>

(2)定义LayoutAnimation

// res/anim/anim_layout.xml
<layoutAnimationxmlns:android="http://schemas.android.com/apk/res/android"android:delay="0.5"android:animationOrder="normal"android:animation="@anim/anim_item" />
  • android:delay:子元素开始动画的时间延迟,比如子元素入场动画的时间周期为300ms,则0.5表示每个子元素都需要延迟150ms再播放动画
  • android:animationOrder:子元素动画顺序。normal表示顺序显示,排在前面的子元素先播放动画;reverse表示逆向显示;random则表示随机播放动画
  • android:animation:指定具体的动画,这里指定(1)中定义的动画

(3)为ViewGroup指定android:layoutAnimation属性

<ListView......android:layoutAnimation="@anim/anim_layout" />

除了在XML中指定LayoutAnimation外,还可以通过LayoutAnimationController实现

ListView listView = findViewById(R.id.list);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.anim_item);
LayoutAnimationController controller = new LayoutAnimationController(animation);
controller.setDelay(0.5f);
controller.setOrder(LayoutAnimationController.ORDER_NORMAL);
listView.setLayoutAnimation(controller);

Activity的切换效果

通过overridePendingTransition(int enterAnim, int exitAnim)方法实现

  • enterAnim:打开Activity时所需的动画资源id
  • exitAnim:Activity被暂停时所需的动画资源id
// 启动Activity
Intent intent = new Intent(this, TestActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim);// 退出Activity
@Override
public void finish() {super.finish();overridePendingTransition(R.anim.enter_anim, R.anim.exit_anim);
}

Fragment的切换效果

可以通过FragmentTransaction中的setCustomAnimations()方法来添加切换动画,注意这里的动画需要是View动画,因为Fragment和属性动画都是API 11新引入的

7.2 帧动画

(1)通过XML定义一个AnimationDrawable

// res/drawable/frame_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="false"><item android:drawable="@drawable/image1" android:duration="500" /><item android:drawable="@drawable/image2" android:duration="500" /><item android:drawable="@drawable/image3" android:duration="500" />
</animation-list>

(2)使用AnimationDrawable

Button mButton = findViewById(R.id.button1);
mButton.setBackgroundResource(R.drawable.frame_animation);
AnimationDrawable drawable = (AnimationDrawable) mButton.getBackground();
drawable.start();

帧动画比较容易引起OOM,所以在使用帧动画时应尽量避免使用过多尺寸较大的图片

7.3 属性动画

1.使用属性动画

(1)属性动画可以对任意对象的属性进行动画而不仅仅是 View

(2)可以实现的效果是:在一个时间间隔内完成对象从一个属性值到另一个属性值的改变,默认间隔为 300ms,默认帧率为 10ms/帧

(3)可以通过代码或 XML 文件两种方式使用属性动画

代码实现

属性动画涉及到的动画类有 ValueAnimator、ObjectAnimator、AnimatorSet

(1)ObjectAnimator:继承自 ValueAnimator,通过调用 ofXxx() 方法指定对象、属性、数值,Xxx为数值类型,最后调用 start() 方法

ObjectAnimator.ofFloat(myObject, "translationY", -myObject.getHeight()).start()

(2)ValueAnimator:本身不作用于任何对象,通常通过上面 ObjectAnimator 的执行返回一个 ValueAnimator,再修改属性

ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", ..., ...);
colorAnim.setDuration(3000);
colorAnim.start();

(3)AnimatorSet:动画集合,可以调用 playTogether() 方法定义一组动画

AnimatorSet set = new AnimatorSet();
set.playTogether(ObjectAnimator.ofFloat(myView, "rotationX", 0, 360)...
);
set.setDuration(5000).start();

XML 实现

主要涉及三个标签:<objectanimator>、<animator>、<set>

(1)<objectanimator>:对应于 ObjectAnimator,主要包含以下属性

  • android:propertyName:表示属性动画的作用对象的属性名称
  • android:duration:表示动画的时长
  • android:valueFrom:表示属性的起始值
  • android:valueTo:表示属性的结束值
  • android:startOffset:表示动画的延迟时间,即动画开始后,需要延迟多少毫秒才开始真正播放此动画
  • android:repeatCount:表示动画的重复次数,默认值为0,-1表示无限循环
  • android:repeatMode:表示动画的重复模式
    • repeat:连续重复,动画每次都是重新开始播放
    • reverse:逆向重复,第一次播放完后第二次倒着播放,如此反复
  • android:valueType:表示 android:propertyName 指定的属性的类型
    • 有 intType 和 floatType 两个可选项,分别表示属性的类型为整型和浮点型
    • 如果 android:propertyName 指定的属性表示的是颜色,则不需要指定该属性,系统会自动对颜色类型的属性做处理

2.插值器与估值器

插值器

(1)TimeInterpolator,时间插值器,作用是根据时间改变的百分比来计算当前属性改变的百分比

(2)系统预置的插值器有

  • LinearInterpolator:线性插值器,匀速动画
  • AccelerateDecelerateInterpolator:加速减速插值器,动画先加速后减速,即两头慢中间快
  • DecelerateInterpolator:减速插值器,动画越来越慢

估值器

(1)TypeEvaluator,类型估值算法,作用是根据当前属性改变的百分比来计算改变后的属性值

(2)系统预置的估值器有

  • IntEvaluator:针对整型属性
  • FloatEvaluator:针对浮点型属性
  • ArgbEvaluator:针对 Color 属性

自定义

自定义插值器需要实现 Interpolator 或者 TimeInterpolator

自定义估值算法需要实现 TypeEvaluator

如果对其他类型(除 int float Color),必须要自定义类型估值算法

3.监听器

属性动画提供了监听器用于监听动画的播放过程,主要有两个接口:AnimatorUpdateListener 和 AnimatorListener

(1)AnimatorListener

  • 可以监听动画的开始、结束、取消以及重复播放
  • 对应实现 onAnimationStart \ End \ Cancel \ Repeat 方法

(2)AnimatorUpdateListener

  • 实现 onAnimationUpdate() 方法
  • 用于监听整个动画过程,动画每播放一帧,onAnimationUpdate() 就会被调用一次

4.对任意属性做动画

(1)在实际开发使用属性动画时,想要动画生效,需要对应的对象满足两个条件

  • 对象必须提供对应属性的 set 方法,如果使用动画的时候没有给定初始值,则还需要提供 get 方法,方便取该属性的初始值

  • 对象提供的 set 方法对该属性的改变必须能够通过某种方法反映出来,比如能改变 UI

(2)两个条件缺一不可,如果条件一不满足则程序直接 Crash,如果条件二不满足则动画无效果但不会 Crash

(3)当两条件不满足时,可以有三种解决办法

  • 给对象加上 getter 和 setter
  • 用一个类来包装原始对象,间接为其提供 getter 和 setter
private void performAnimate() {ViewWrapper wrapper = new ViewWrapper(mButton);ObjectAnimator.ofInt(wrapper, "width", 500).setDuration(5000).start();
}private static class ViewWrapper {private View mTarget;public ViewWrapper(View target) {mTarget = target;}public int getWidth() {return mTarget.getLayoutParams().width;}public void setWidth(int width) {mTarget.getLayoutParams().width = width;mTarget.requestLayout();}
}
  • 借助 ValueAnimator,监听动画过程,在动画过程中修改对象的属性值,从而实现属性的改变

5.工作原理

ObjectAnimator.start

(1)start() 内首先会判断如果当前动画、等待动画(Pending)和延迟动画(Delay)中有和当前动画相同的动画,则将相同的动画取消掉

(2)然后调用 super.start(),之前说过 ObjectAnimator 继承自 ValueAnimator,因此调用 ValueAnimator 内的 start 方法

(3)ValueAnimator 内的 start 方法内会经历如下过程

  • 属性动画运行在有 Looper 的线程中
  • 最终会调用 AnimationHandler 的 start 方法
  • 这个 AnimationHandler 并非 Handler,而是一个 Runnable,在它的 run() 内会调用 ValueAnimator 的 doAnimationFrame 方法

(4)doAnimationFrame 方法又会调用 animationFrame() ,进而调用 animateValue() 方法

(5)最后在 animateValue() 中调用 calculateValue() 方法计算每帧动画所对应的属性的值,从而完成改变

get

(1)之前说过,在初始化的时候,如果属性的初始值没有提供,则 get 方法将会被调用

(2)这个过程发生在 PropertyValuesHolder 的 setuoValue方法中,在这个方法中可以看出 get 方法是通过反射来调用的

set

(1)当动画的下一帧到来时,PropertyValuesHolder 中的 setAnimatedValue 方法会将新的属性值设置给对象

(2)其中调用 setter 方法也是通过反射来调用的

7.4 使用动画的注意事项

OOM 问题

主要出现在帧动画中,当图片数量较多且图片较大时极容易出现 OOM,实际开发应尽量避免使用帧动画

内存泄露

主要针对属性动画中的循环动画,这类动画需要在Activity 退出时即时停止,否则会导致 Activity 无法释放从而造成内存泄露

View 动画的问题

View 动画有时会出现动画完成后 View 无法隐藏的现象,即 setVisibility(GONE) 失效,此时可调用 view.clearAnimation() 消除动画

不要使用 px

尽量使用 dp 而非 px,px 可能会导致适配问题

硬件加速

使用动画的过程中,建议开启硬件加速,这样会提高动画的流畅性

Connor学Android - Android动画相关推荐

  1. Connor学Android - JNI和NDK编程

    Learn && Live 虚度年华浮萍于世,勤学善思至死不渝 前言 Hey,欢迎阅读Connor学Android系列,这个系列记录了我的Android原理知识学习.复盘过程,欢迎各位 ...

  2. Connor学Android - Bitmap的加载和缓存策略

    Learn && Live 虚度年华浮萍于世,勤学善思至死不渝 前言 Hey,欢迎阅读Connor学Android系列,这个系列记录了我的Android原理知识学习.复盘过程,欢迎各位 ...

  3. Connor学Android - RootView、DecorView、MeasureSpec

    Learn && Live 虚度年华浮萍于世,勤学善思至死不渝 前言 Hey,欢迎阅读Connor学Android系列,这个系列记录了我的Android原理知识学习.复盘过程,欢迎各位 ...

  4. Android技能树 — 动画小结

    最近整理了下自己学过的动画方面的知识.用百度脑图做了动画知识的思维脑图,哪里如果觉得不对,大家可以留言提出哦. 你没看错,掘金的文章的图片,电脑上看这种思维脑图根本就看不清楚,所以我准备一块块来讲.( ...

  5. Android属性动画,和ButterKnife的使用方法

    目录 1.属性动画 1.什么是属性动画 2.ValueAnimator的使用方法 1.首先先创建四个按钮和一个图片 ,还要给布局设置ID 2.接下来在MainActivity里进行动画操作,这个是上下 ...

  6. android+属性动画+高度,android 自定义view+属性动画实现充电进度条

    近期项目中需要使用到一种类似手机电池充电进度的动画效果,以前没学属性动画的时候,是用图片+定时器的方式来完成的,最近一直在学习动画这一块,再加上复习一下自定义view的相关知识点,所以打算用属性动画和 ...

  7. android 揭示动画_揭示自动驾驶汽车第4级和第5级的真实含义

    android 揭示动画 Dr. Lance Eliot, AI Insider AI Insider博士Lance Eliot博士 [Ed. Note: For reader's intereste ...

  8. Android之动画全讲-刘志远-专题视频课程

    Android之动画全讲-7291人已学习 课程介绍         本课程讲解了Android中的帧动画,补间动画,属性动画的动画实现过程 课程收益     让学员掌握Android中基本的动画形式 ...

  9. android 揭示动画_有史以来最好的策略来揭示出色的想法

    android 揭示动画 为什么我们在考虑时间优化完全错误 (Why we are thinking about time optimisation completely wrong) Technol ...

最新文章

  1. MySQL 数据库的优化,你知道有哪些?
  2. android text字体居中显示,Android Canvas的drawText()和文字居中方案
  3. 16年寒假随笔(4)
  4. cogs 1456. [UVa 10881,Piotr's Ants]蚂蚁
  5. VS2010与OpenCV2410简单配置
  6. 如何画好一套线性图标
  7. Android App安全防范措施的小结
  8. 实现图片抠图,拖拽验证功能
  9. vue-router路由文档详解
  10. 叮铃铃~: 一个Vue铃声/提示音组件
  11. 【推】如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧
  12. 2022最新教程,半小时速通Git和Github的基本操作。
  13. 利用反射等离激元超表面的模拟光计算
  14. 【考研政治】1. 导论和基本哲学问题
  15. python灰产路子有哪些_Python3 网络爬虫(四):视频下载,那些事儿!-后台/架构/数据库-敏捷大拇指-一个敢保留真话的IT精英社区...
  16. 微信公众号访问本地服务器的方法
  17. 软件测试是干什么的 发展前景怎样?
  18. c语言基础输入printf,C语言输入输出 -printf()输出格式大全
  19. JAVA基础控制台版本演示增删改查项目(带完整源码)
  20. maven无法找到idk中的类

热门文章

  1. protobuf网络传输协议的优缺点
  2. 使用图灵机器人做简单的聊天系统
  3. python 图片正方形化
  4. 登录滑块验证表单_如何构建双滑块登录和注册表单
  5. 五年级上册计算机教学工作计划,小学五年级上册信息技术教学工作计划(精选5篇)...
  6. oracle01109,oracle解锁用户时报错ORA-01109: database not open的解决办法
  7. ssssssssss
  8. spark.read.option参数
  9. 【Linux】【下载工具】Linux系统命令行下载工具汇总
  10. python爬虫-世界今日疫情爬虫