Android的动画可以分为三种:View动画、帧动画和属性动画,其实帧动画也属于View动画的一种,只不过它和平移、旋转等常见的View动画在表现形式上略有不同而已。
一、 View动画
View动画有四种变化效果,Translate、Scale、Rotate和Alpha,这四种动画既可以通过XML来定义,也可以通过代码来动态创建。
名称 | 标签 | 子类 | 效果 |
---|---|---|---|
平移动画 | <translate> | TranslateAnimation | 移动View |
缩放动画 | <scale> | ScaleAnimation | 放大或缩小View |
旋转动画 | <rotate> | RotateAnimation | 旋转View |
透明度动画 | <alpha> | AlphaAnimation | 改变View的透明度 |
<?xml version="1.0" encoding="utf-8"?>
<!-- res/anim -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<alpha
android:fromAlpha="float"
android:toAlpha="float"/>
<scale
android:fromXScale="float"
android:toXScale="float"
android:fromYScale="float"
android:toYScale="float"
android:pivotX="float"
android:pivotY="float"/>
<translate
android:fromXDelta="float"
android:toXDelta="float"
android:fromYDelta="float"
android:toYDelta="float"/>
<rotate
android:fromDegrees="float"
android:toDegrees="float"
android:pivotX="float"
android:pivotY="float" />
</set>
接下来具体讲下一下各类型用法:
1. Translate
<translate>标签表示平移动画,对应TranslateAnimation类,它可以使一个View在水平和竖直方向完成平移的动画效果:
- android:fromXDelta —— 表示x的起始值
- android:toXDelta —— 表示x的结束值
- android:fromYDelta —— 表示y的起始值
- android:toYDelta —— 表示y的结束值
接下来使用translate使一个View在2秒内在水平方向平移400长度,垂直方向平移100长度,并使其停留在移动后的位置(fillAfter)
- 用法一:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<translate
android:fromXDelta="0"
android:toXDelta="400"
android:fromYDelta="0"
android:toYDelta="100"
android:duration="2000"/>
</set>
private void translate(){
Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate);
block.startAnimation(animation);
}
- 用法二:
private void translate(){
TranslateAnimation animation = new TranslateAnimation(Animation.ABSOLUTE, 0,
Animation.ABSOLUTE, 400, Animation.ABSOLUTE, 0, Animation.ABSOLUTE, 100);
animation.setDuration(2000);
animation.setFillAfter(true);
block.startAnimation(animation);
}
TranslateAnimation共有三个构造函数,分别是:
主要看一下第三个构造函数:
TranslateAnimation(int fromXType, float fromXDelta, int toXType, float toXDelta,
int fromYType, float fromYDelta, int toYType, float toYDelta)
我们会发现每个value前都有一个type
- Animation.ABSOLUTE,表示为绝对像素,此时XValue和YValue参数的含义和第二个构造函数相同。
- Animation.RELATIVE_TO_SELF,表示相对位移量了,举个例子来说,如果在X方向上选择Animation.RELATIVE_TO_SELF,那么当XValue=1.0f时,则偏移量为一个自身宽度。
- Animation.RELATIVE_TO_PARENT,则表示相对位移量了,如果在X方向上选择Animation.RELATIVE_TO_PARENT时,则偏移量为一个父控件宽度。
2. Scale
<scale>标签表示缩放动画,对应ScaleAnimation类,它可以使一个View具有放大或者缩小的动画效果:
- android:fromXScale —— 水平方向缩放的起始值(是原始值的倍数)
- android:toXScale —— 水平方向缩放的结束值(是原始值的倍数)
- android:fromYScale —— 垂直方向缩放的起始值(是原始值的倍数)
- android:toYScale —— 垂直方向缩放的结束值(是原始值的倍数)
- android:pivotX —— 缩放的轴点的x坐标,会影响缩放效果
- android:pivotY —— 缩放的轴点的y坐标,会影响缩放效果
接下来使用scale使一个View在2秒内以其原点为轴点在水平方向和垂直方向都放大为原来的2倍,并保留变化后的状态
- 用法一:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:fromXScale="1"
android:toXScale="2"
android:fromYScale="1"
android:toYScale="2"
android:pivotX="0"
android:pivotY="0"
android:duration="2000"/>
</set>
private void scale(){
Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);
block.startAnimation(animation);
}
- 用法二:
private void scale(){
ScaleAnimation animation = new ScaleAnimation(1, 2, 1, 2, Animation.RELATIVE_TO_SELF, 0,
Animation.RELATIVE_TO_SELF, 0);
animation.setDuration(2000);
animation.setFillAfter(true);
block.startAnimation(animation);
}
ScaleAnimation共有四个构造函数,分别是:
主要看一下第四个构造函数:
ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue,
int pivotYType, float pivotYValue)
pivotXValue和pivotYValue前的Type与之前提到的一样,表示坐标的一个相对位移
3. Rotate
<rotate>标签表示旋转动画,对应RotateAnimation类,它可以使一个View具有旋转的动画效果:
- android:fromDegrees —— 旋转开始的角度
- android:toDegrees —— 旋转结束的角度
- android:pivotX —— 旋转的轴点的x坐标
- android:pivotY —— 旋转的轴点的y坐标
接下来使用rotate使一个View在2秒内以其右下角为轴点旋转90度,并保留变化后的状态
- 用法一:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<rotate
android:fromDegrees="0"
android:toDegrees="90"
android:pivotX="80"
android:pivotY="80"
android:duration="2000"/>
</set>
private void rotate(){
Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate);
block.startAnimation(animation);
}
- 用法二:
private void rotate(){
RotateAnimation animation = new RotateAnimation(0, 90, Animation.RELATIVE_TO_SELF, 1,
Animation.RELATIVE_TO_SELF, 1);
animation.setDuration(2000);
animation.setFillAfter(true);
block.startAnimation(animation);
}
RotateAnimation共有四个构造函数,分别是:
4. Alpha
<alpha>标签表示透明度动画,对应AlphaAnimation类,它可以改变View的透明度:
- android:fromAlpha —— 表示透明度的起始值
- android:toAlpha —— 表示透明度的结束值
接下来使用alpha使一个View在2秒内变成完全透明度为0.2,并保留变化后的状态
- 用法一:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<alpha
android:fromAlpha="1"
android:toAlpha="0.2"
android:duration="2000"/>
</set>
private void alpha(){
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha);
block.startAnimation(animation);
}
- 用法二:
private void alpha(){
AlphaAnimation animation = new AlphaAnimation(0, 0.2f);
animation.setDuration(2000);
animation.setFillAfter(true);
block.startAnimation(animation);
}
AlphaAnimation共有两个构造函数,分别是:
二、 帧动画
帧动画是顺序播放一组预先定义好的图片,类似于电影播放。不同于View动画,系统提供了另外一个类AnimationDrawable来使用帧动画
<?xml version="1.0" encoding="utf-8"?>
<!-- res/drawable -->
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item android:drawable="@drawable/pic1" android:duration="500"/>
<item android:drawable="@drawable/pic2" android:duration="500"/>
<item android:drawable="@drawable/pic3" android:duration="500"/>
</animation-list>
private void frame(){
block.setBackgroundResource(R.drawable.frame);
AnimationDrawable drawable = (AnimationDrawable) block.getBackground();
drawable.start();
}
onshot为false表示循环播放,不过必须在animation-list的最后多加一帧第一帧动画,如下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="true">
<item android:drawable="@drawable/pic1" android:duration="500"/>
<item android:drawable="@drawable/pic2" android:duration="500"/>
<item android:drawable="@drawable/pic3" android:duration="500"/>
<item android:drawable="@drawable/pic1" android:duration="500"/>
</animation-list>
三、 属性动画
属性动画,可以在一个时间间隔内完成对象从一个属性值到另一个属性值得改变。但是属性动画从API11才有,一定程度上制约了属性动画的使用。
<?xml version="1.0" encoding="utf-8"?>
<!-- res/animator -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering=["together"|"sequentially"]>
<objectAnimator
android:propertyName="string"
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["restart"|"reverse"]
android:valueType=["intType"|"floatType"]/>
<animator
android:duration="int"
android:valueFrom="float | int | color"
android:valueTo="float | int | color"
android:startOffset="int"
android:repeatCount="int"
android:repeatMode=["restart"|"reverse"]
android:valueType=["intType"|"floatType"]/>
</set>
属性动画的各种参数都比较好理解,在XML中可以定义ValueAnimator、ObjectAnimator以及AnimatorSet,其中<set>标签对应AnimatorSet,<animator>标签对应ValueAnimator,而<objectAnimator>标签对应ObjectAnimator。
set标签里有两个可选值:"together"和"sequentially",其中"together"表示动画集合中的子动画同时播放,"sequentially"则表示动画集合中的子动画按照前后顺序依次播放,默认为"together"。
其他属性:
- android:propertyName —— 表示属性动画的作用对象的属性的名称
- android:duration —— 表示动画的时长
- android:valueFrom —— 表示属性的起始值
- android:valueTo —— 表示属性的结束值
- android:startOffset —— 表示动画的延迟时间,当动画开始后,需要延迟多少毫秒才会真正执行动画
- android:repeatCount —— 表示动画的重复次数
- android:repeatMode —— 表示动画的重复模式
- android:valueType —— 表示android:propertyName所指定的属性的类型,intType为整型,floatType为浮点型,如果属性表示的是颜色,则不需要指定valueType
试下来使用属性动画实现一个View的背景颜色在3秒内从#0xFFFF8080到#0xFF8080FF的渐变,动画会无限循环且有反转的效果
用法一:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:propertyName="backgroundColor"
android:duration="3000"
android:valueFrom="#FF8080"
android:valueTo="#8080FF"
android:startOffset="0"
android:repeatCount="infinite"
android:repeatMode="reverse">
</objectAnimator>
private void objectAnimator(){
ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(this, R.animator.object);
animator.setEvaluator(new ArgbEvaluator());
animator.setTarget(block);
animator.start();
}
用法二:
private void objectAnimator(){
ValueAnimator colorAnim = ObjectAnimator.ofInt(this, "backgroundColor", Color.parseColor("#FF8080"),
Color.parseColor("#8080FF"));
colorAnim.setDuration(3000);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.setTarget(block);
colorAnim.start();
}
试下来使用属性动画在3秒内同时实现一个View的背景颜色和透明度的渐变
用法一:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<objectAnimator
android:propertyName="alpha"
android:duration="3000"
android:valueTo="0.2"
android:valueType="floatType"/>
<objectAnimator
android:propertyName="backgroundColor"
android:duration="3000"
android:valueFrom="#FF8080"
android:valueTo="#8080FF"
android:valueType="colorType"/>
</set>
private void animatorSet(){
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.set);
set.setTarget(block);
set.start();
}
用法二:
private void animatorSet(){
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofInt(this, "backgroundColor", Color.parseColor("#FF8080"),
Color.parseColor("#8080FF")),
ObjectAnimator.ofFloat(this, "alpha", 1, 0.2f)
);
set.setTarget(block);
set.start();
}
如果在构建ObjectAnimator随便传一个属性过去,轻则没动画效果,重则程序直接Crash。
这种情况下可以采用ValueAnimator,监听动画过程,自己实现属性的改变:
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
valueAnimator.addUpdateListener(new AnimatorUpdateListener(){
@Override
public void onAnimationUpdate(ValueAnimator animator){
// 获得当前动画的进度值,1~100之间
int currentValue = (Integer) animator.getAnimatedValue();
requestLayout(); // 根据进度值改变布局
}
});
valueAnimator.setDuration(5000).start();
哈哈,安卓的动画基础大概就这些,如果想要熟练掌握还需勤加练习~~