Android中动画分为三类:
(1)帧动画 Frame
(2)补间动画 Tween
(3)属性动画 Property
一.补间动画
先讲补间动画是因为它的4个属性比较常用。
(1)alpha 透明度
(2)translate 位移
(3)scale 缩放
(4)rotate 旋转
1.单个动画的实现
(1)先写animaction文件到anim文件夹中
有上边的4种标签和<set>标签,例如
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="0.0" />
多种动画效果时
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000">
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:toAlpha="0.0" />
<translate
android:fromXDelta="0"
android:toXDelta="100"
android:fromYDelta="100"
android:toYDelta="0"
/>
</set>
(2)获取动画对象
Animation animation = AnimationUtils.loadAnimation(this,R.anim.set_anim);
这里有两个重要的动画相关类Animation 和AnimationUtils后面会讲。我觉得这两个类应该背下来。
(3)设置动画
view.startAnimation(animation);
可以顺便看看,view可以设置的和动画相关的方法有这些
2.四种属性的属性值
(1)都能用的
duration : 动画持续的时间
Interpolator:变速
(2)alpha
fromAlpha : 开始的透明度
toAlpha : 结束时的透明度
(3)translate
fromXDelta : x起始位置(当前view的位置为0,0)
toXDelta : x结束位置
fromYDelta : y起始位置
toYDelta : y结束位置
(4)scale
fromXScale : 水平缩放的起始点
pivotX : 缩放中心点的 X 坐标
toXScale : 水平缩放的结束点
PS: Y的属性和X一样
(5)rotate
fromDegrees:旋转开始的角度
toDegrees :旋转结束的角度
pivotX : 旋转中心点的 X 坐标
pivotY : 旋转中心点的 Y 坐标
二.帧动画
帧动画有个关键词叫:Animation-list
1.实现
(1)在drawable目录下添加帧图片
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true" >
<item
android:drawable="@drawable/d1"
android:duration="150" />
<item
android:drawable="@drawable/d2"
android:duration="150" />
<item
android:drawable="@drawable/d3"
android:duration="150" />
</animation-list>
oneshot表示是否只播放一次
duration表示每张图的播放时间
(2)添加动画
因为是drawable,所以可以直接给imageview设置,之后执行动画的播放等操作
AnimationDrawable animationDrawable = (AnimationDrawable) mImgView.getDrawable();
if(!animationDrawableBg.isRunning()) {
animationDrawableBg.start();
}
这里又涉及到了一个类: AnimationDrawable ,加上补间动画中的Animation和AnimationUtils,目前就出现了3个和动画相关的类。
(3)其实除了使用xml添加动画,还可以动态去添加帧动画
AnimationDrawable mAnimationDrawableBg = new AnimationDrawable();
mAnimationDrawableBg .addFrame(getResources().getDrawable(R.drawable.d1), 150);
mAnimationDrawableBg .addFrame(getResources().getDrawable(R.drawable.d2), 150);
mAnimationDrawableBg .addFrame(getResources().getDrawable(R.drawable.d3), 150);
mAnimationDrawableBg .setOneShot(false);
注意,多处添加同一个AnimationDrawable 对象,只会在最后一个生效
2.AnimationDrawable
看看这个和帧动画相关的类有哪些常用的方法
(1)start()开始
(2)stop()停止
(3)isRunning()判断动画是否正在播放
(4)isOneShot()判断是否只执行一次
(5)setOneShot()设置动画是否只执行一次
(6)addFrame(@NonNull Drawable frame, int duration)添加帧
帧动画有个明显的缺点,每一帧都是一张图片,所以设置得不好的话就会增大apk。
三.属性动画
属性动画一听就知道是和对象属性相关的动画。他和补间动画的区别在于他的属性变了,而补间动画的属性没变。举个简单的例子,同样是位移动画,补间动画位移完之后会回到原位,而属性不会。
这个属性动画有个动画相关类,叫ObjectAnimator,加上前3个,目前为止就4个比较重要的动画相关类了。
(1)Animation和AnimationUtils -> 补间动画
(2)AnimationDrawable -> 帧动画
(3)ObjectAnimator -> 属性动画
然后我本来是想看ObjectAnimator 这个类中的源码的,结果都是
public ObjectAnimator() {
throw new RuntimeException("Stub!");
}
好吧,那我就展示不看了,浏览下总体结构再结合网上说的一些常用的方法来归纳吧。
1.实现
ObjectAnimator anim = ObjectAnimator.ofFloat(btn, "translationX", 300);
anim.setDuration(300);
anim.start();
首先是ofFloat方法,比较主要的,能获取到ObjectAnimator对象,这里需要传3个参数
(1)Object,传需要执行属性动画的对象
(2)propertyName , 属性名
(3)float... values , 这是一个不定的浮点型数组,这个参数会根据是什么动画而不同。如果我瞎传,得到的动画效果也会很乱。
setDuration就是时间,start就是开始,这没什么好说的。
既然它能够实现补间动画的效果,那我们就先来用属性动画实现补间动画的4种属性。
2.属性动画实现透、移、转、缩
(1)透明效果
ObjectAnimator animator = ObjectAnimator.ofFloat(imageView, "alpha", 1, 0);
animator.setDuration(500);
animator.start();
属性名是alpha,后面的数组中两个参数,1表示显示,0表示隐藏,这里就表示从显示到隐藏,如果传的是0,1就表示从隐藏到显示。
你也可以脑洞大开像我这样玩
ObjectAnimator anim = ObjectAnimator.ofFloat(objView, "alpha", 1,0,1,0);
这样就会显示到隐藏,再显示再隐藏。而这也体现数第三个数组的一个效果,那就是表示一套动画的效果
这还没玩完,我们再脑洞大开,打开手机的“调试GPU过度绘制”,你会发现最后隐藏时,原先View的那块的绘制减了一层,说明View是真的被隐藏,也就是说属性以被改变。
(2)位移
ObjectAnimator anim = ObjectAnimator.ofFloat(objView, "translationX", 0,100,200,200);
anim.setDuration(5000);
anim.start();
这里的动画表示从0位移到100,再从100位移到200,再从200位移到200(不变)。但是我试过,第三个参数数组传一个参数也行,就是从0到那个参数。
当然Y轴就是translationY。
(3)旋转
ObjectAnimator anim = ObjectAnimator.ofFloat(objView, "rotation", 0,180,0,180,360);
anim.setDuration(6000);
anim.start();
属性是rotation,角度我的代码体现也很明显,不多说
除了这样平面旋转之外,用rotation也可以实现轴心旋转
ObjectAnimator anim = ObjectAnimator.ofFloat(objView, "rotationX", 90,360);
anim.setDuration(500);
anim.start();
比如这样就实现了绕X轴旋转,但是我测试的时候view是消失了,然后查了一下原因,有网友说是华为手机的某些系统会出现这样的问题,那看来这种动画还需要留意机型适配
(4)缩放
ObjectAnimator anim = ObjectAnimator.ofFloat(objView, "scaleX", 1,2);
anim.setDuration(6000);
anim.start();
scaleX表示往X方向缩放,第三个参数表示缩放的倍数。
那其实做到这里可能会有人问,我想同时往X和Y进行缩放怎么办,不要急,这里就需要使用到组合动画。
3.属性动画组合
这里就需要用到一个类:AnimatorSet
比如我们组合一个动画
ObjectAnimator anim = ObjectAnimator.ofFloat(objView, "rotation", 90,360);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(objView, "translationX", 0,200);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(objView, "alpha", 1,0);
AnimatorSet set = new AnimatorSet();
set.play(anim).with(anim).with(anim2).with(anim3);
set.setDuration(3000);
set.start();
这样写的话就会3种动画会同时被执行
这里AnimatorSet内部使用的是一个builder模式,有几种属性
(1)play()设置第一个动画
(2)with()同时执行的动画
(3)before()在动画之前执行的动画
(4)after()在动画之后执行的动画
(5)after(time)延迟多少秒执行
除了用play外,还可以用playTogether方法组合,例如
set.playTogether(anim,anim3,anim2);
当然AnimatorSet可以设置同一个对象组合动画外,还可以设置多个对象同时进行组合动画,例如
ObjectAnimator anim = ObjectAnimator.ofFloat(objView, "rotation", 90,360);
ObjectAnimator anim2 = ObjectAnimator.ofFloat(objView2, "translationX", 0,200);
ObjectAnimator anim3 = ObjectAnimator.ofFloat(objView, "alpha", 1,0,1);
AnimatorSet set = new AnimatorSet();
set.playTogether(anim,anim3,anim2);
// set.play(anim).with(anim3).after(anim2);
set.setDuration(3000);
set.setStartDelay(500);
set.start();
这里就有objView和objView2两个对象。
扩展一下,我在使用组合动画的时候确实是使用AnimatorSet对象来操作,但是我查资料的时候发现除了AnimatorSet外,PropertyValuesHolder也能实现动画的组合
PropertyValuesHolder anim = PropertyValuesHolder.ofFloat("rotation", 90,360);
PropertyValuesHolder anim2 = PropertyValuesHolder.ofFloat("translationX", 0,200);
PropertyValuesHolder anim3 = PropertyValuesHolder.ofFloat("alpha", 1, 0, 1);
ObjectAnimator.ofPropertyValuesHolder(objView, anim, anim2, anim3).setDuration(1000).start();
注意一下,虽然这两种方法都能实现动画的组合,但是概念是不一样的啊,第一种用AnimatorSet是指多个动画对象一起组合播放,第二种方法PropertyValuesHolder是指多种动画效果合并成一个动画。所以具体用哪种好,是根据它的概念去决定的。
可以设置动画的监听
anim.addListener(new AnimatorListenerAdapter(){......})
然后AnimatorListenerAdapter可以重写这些方法
这里方法名就很清楚具体哪个方法监听哪一步。具体用到拿个就写哪个。
除了AnimatorListenerAdapter这个类外,还有一个类 Animator.AnimatorListener()也能实现监听。
4.xml实现
如果需要用xml定义动画,在anim文件中用<objectAnimator >标签定义就行,这个我没用过,我比较建议去动态创建动画,除非你有在多处复用的属性动画。
四.总结
我自己也没想到android动画相关的内容会这个多,如果不写博客,也许我还停留在动画只有透明、移动、旋转、缩放这些。去查去尝试之后才发现动画这个系统真的是挺庞大的,而且我这也没讲完,只是讲了基本的用法和组合。还有很多内容没讲
(1)每个动画相关类中的大致内容
(2)ObjectAnimator是继承ValueAnimator这个也没讲
(3)自定义动画,这个也没讲
(4)Android动画的一些原理和流程,这个很重要
(5)一些常见的高逼格的效果也没讲
......
所以要去发现,要去总结的动画相关的内容还有好多,一篇肯定是讲不完了,所以打算分几篇也说,最后再对所有讲过的东西进行一个二次总结。这篇讲的都是一些皮毛,精彩未完,待续...