今天道长说一下属性动画。毕竟现在手机app上基本上都会有动画的存在,像一些界面的切换,加载等等。属性动画是在Android3.0引入的,在此之前,帧动画和补间动画一起雄霸天下,那时的动画还不怎么复杂和炫酷,直到属性动画的出现让一些疯狂的产品经理在app中大量的添加动画甚至组合动画的需求……
一、三种动画
帧动画(frame-by-frame animation):顾名思义就是将一个完整的动画拆分成一张张单独的图片,然后再将它们连贯起来进行播放,类似于动画片的工作原理。
补间动画(tweened animation):则是可以对View进行一系列的动画操作,包括淡入淡出、缩放、平移、旋转四种。
- 补间动画有两个缺陷:
1.补间动画只能够作用在承自View的组件上的,不可对非View的对象进行操作。
2.补间动画不对控件原有属性改变,也就是说View的淡入淡出、缩放、平移、旋转四种动画执行完,该View的位置,颜色,大小等等属性都没有改变。
属性动画(property animation):功能非常强大,弥补了之前补间动画的一些缺陷,几乎是可以完全替代掉补间动画
二、属性动画
补间动画和帧动画的出现比较早了,有很多功能的实现都已经被属性动画替代,这里道长就不过多讲关于补间动画和帧动画的内容了。
1.ObjectAnimator
对一个View进行动画操作,ObjectAnimator是我们最常接触到的类,可以直接对任意对象的任意属性进行动画操作
- 透明度
TextView在5秒内从常规变换成全透明,再从全透明变换成常规:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
animator.setDuration(5000);
animator.start();
- 旋转
TextView在5秒内进行一次360度的旋转:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
animator.setDuration(5000);
animator.start();
- 平移
TextView在5秒内先向左移出屏幕,然后再移动回来:
float curTranslationX = textview.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "translationX", curTranslationX, -500f, curTranslationX);
animator.setDuration(5000);
animator.start();
这里道长调用了TextView的getTranslationX()方法来获取到当前TextView的translationX的位置,然后ofFloat()方法的第二个参数传入”translationX”告诉TextView要水平移动,紧接着后面三个参数用于告诉系统TextView应该怎么移动
- 缩放
TextView5秒内在垂直方向上放大3倍再还原,就可以这样写:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "scaleY", 1f, 3f, 1f);
animator.setDuration(5000);
animator.start();
ObjectAnimator中的常用方法:
- setStartDelay() - 设置动画延迟播放的时间
- setRepeatCount() - 设置动画循环播放的次数
- setRepeatMode() - 设置动画循环播放的模式,循环模式包括RESTART和REVERSE两种,分别表示重新播放和倒序播放。
2.XML编写动画
除了使用代码动态编写动画外还可以使用xml编写动画,使用xml编写的动画复用率比较高,可以大大减少app的体量,当然有利有弊,使用xml编写动画要比代码编写要慢,而且没有代码编写灵活。
要使用xml编写动画,首先要在res目录下面新建一个anim文件夹,所有属性动画的XML文件都应该存放在这个文件夹当中。然后在XML文件中我们一共可以使用如下三种标签:
<animator> - 对应代码中的ValueAnimator
<objectAnimator> - 对应代码中的ObjectAnimator
<set> - 对应代码中的AnimatorSet
假如要实现一个从0到100平滑过渡的动画,在XML当中就可以这样写:
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="0"
android:valueTo="100"
android:valueType="intType"/>
如果将一个视图的alpha属性从1变成0,就可以这样写:
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType"
android:propertyName="alpha"/>
也可以这样写:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0.0" />
还可以这样写:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="300"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0.0" />
</set>
然后在代码中调用即可:
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim);
animator.setTarget(view);
animator.start();
3.调用View的方法编写动画
虽然TextView中没有alpha之类的属性,但是 ObjectAnimator内部的工作机制并不是直接对我们传入的属性名进行操作的,而是会去寻找这个属性名对应的get和set方法。所以我们也可以使用api编写动画。
view.setRotation(360*fraction);//设置旋转的角度
// view.setRotationX(360*fraction);//设置围绕x轴旋转的角度
// view.setRotationY(360*fraction);//设置围绕Y轴旋转的角度
4.调用NineOldAndroid的方法编写动画
属性动画是Android3.0引入的,如果在Android3.0之前的系统上想要使用属性动画就要使用NineOldAndroid将3.0之后的属性动画和view相关的方法兼容到了3.0之前。
// 使用NineOldAndroid中的方法
// ViewHelper.setRotation(redView, 360*fraction);//设置旋转的角度
ViewHelper.setScaleX(redView, 1+fraction*0.5f);
ViewHelper.setScaleY(redView, 1+fraction*0.5f);
总之实现的方法还是比较多的。
三、组合动画
1.代码编写
上面的就是属性动画独立执行的代码,但是独立的动画能够实现的视觉效果毕竟是相当有限的,因此将多个动画组合到一起播放就显得尤为重要。实现组合动画功能主要需要借助AnimatorSet这个类以及其中的四个方法:
- after(Animator anim) - 将现有动画插入到传入的动画之后执行
- after(long delay) - 将现有动画延迟指定毫秒后执行
- before(Animator anim) - 将现有动画插入到传入的动画之前执行
- with(Animator anim) - 将现有动画和传入的动画同时执行
有了这四个方法,就可以让我们的动画按照逻辑执行了,比如说我们想要让TextView先从屏幕外移动进屏幕,然后开始旋转360度,旋转的同时进行淡入淡出操作,就可以这样写:
ObjectAnimator moveIn = ObjectAnimator.ofFloat(textview, "translationX", -500f, 0f);
ObjectAnimator rotate = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
AnimatorSet animSet = new AnimatorSet();
animSet.play(rotate).with(fadeInOut).after(moveIn);
animSet.setDuration(5000);
animSet.start();
这是一种比较常见的用法,我们也可以这么使用:
public void propertyValuesHolder(View view) {
PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f, 0f, 1f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);
PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f, 0, 1f);
ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY, pvhZ).setDuration(1000).start();
}
2.xml编写
当然我们也可以使用xml编写组合动画:
<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially" >
<objectAnimator
android:duration="2000"
android:propertyName="translationX"
android:valueFrom="-500"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="together" >
<objectAnimator
android:duration="3000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" >
</objectAnimator>
<set android:ordering="sequentially" >
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="1"
android:valueTo="0"
android:valueType="floatType" >
</objectAnimator>
<objectAnimator
android:duration="1500"
android:propertyName="alpha"
android:valueFrom="0"
android:valueTo="1"
android:valueType="floatType" >
</objectAnimator>
</set>
</set>
</set>
选择使用代码编写还是使用xml编写主要看需求了,如果产品需求的复用可能性比较大就用xml,其他的看心情。
四、Animator监听器
一般在动画执行的时候或者动画执行完要去执行逻辑代码,这时候我们就希望可以监听到动画的各种事件,比如动画何时开始,何时结束。
我们可以添加一个监听器来实现监听,如下所示:
anim.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
});
监听接口里的这四个方法就不多说了,如果不想每次都重写这四个方法还可以实现监听适配器这个类,代码如下:
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
}
});
属性动画的基本使用和组合动画就说到这里,一般的需求也就用到这么多,下次道长在说一下属性动画的高级应用。希望这篇博客能为你提供一些帮助。