Android中的动画有三种,分别是补间动画、帧动画、属性动画。
</p>
1. 补间动画
</p>
通过在两个关键帧之间补充渐变的动画效果来实现,其优点是可以节省空间。Android目前支持的补间动画有RotateAnimation(旋转)、ScaleAnimation(缩放)、AlphaAnimation(透明度)、TranslateAnimation(位移)、AnimationSet(组合)这5种。
实现补间动画的方式有两种:1.代码创建 2.使用xml
第一种:使用代码创建:
1.1 RotateAnimation(旋转动画)
/**
* 创建旋转动画
*/
private void createRotateAnimation() {
/**
* 构造方法如下
*fromDegrees、toDegrees表示开始、结束的角度(0度为水平方向右侧的开始角度),pivotXValue、pivotYValue代表旋转的中心位置,[0.0f-1.0f],
*pivotXType、pivotYType表示旋转的类型(Animation.ABSOLUTE,、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT)
*当type为Animation.ABSOLUTE时,这个个值为具体的像素值,当type为Animation.RELATIVE_TO_SELF或Animation.RELATIVE_TO_PARENT,这个个值为比例值,取值范围是[0f, 1.0f]
*public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,int pivotYType, float pivotYValue) { }
*/
//初始化RotateAnimation
RotateAnimation animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
//动画执行时间
animation.setDuration(2000);
//动画重复次数-1表示不停重复
//animation.setRepeatCount(-1);
//给控件设置动画
mTv.startAnimation(animation);
}
1.2 ScaleAnimation(缩放动画)
/**
* 创建缩放动画
*/
private void createScaleAnimation() {
/**
* 构造方法如下
* fromX、toX 开始结束的X轴缩放比率[0.0f-1.0f],fromY、toYtoY开始结束的Y轴缩放比率[0.0f-1.0f],pivotXValue、pivotYValue代表旋转的中心位置,[0.0f-1.0f],
* pivotXType、pivotYType表示旋转的类型(Animation.ABSOLUTE,、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT)
* 当type为Animation.ABSOLUTE时,这个个值为具体的像素值,当type为Animation.RELATIVE_TO_SELF或Animation.RELATIVE_TO_PARENT,这个个值为比例值,取值范围是[0f, 1.0f]
* public ScaleAnimation(float fromX, float toX, float fromY, float toY,int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {}
*/
//初始化ScaleAnimation
ScaleAnimation animation = new ScaleAnimation(1f, 0.5f, 1f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
//动画执行时间
animation.setDuration(2000);
//动画重复次数-1表示不停重复
//animation.setRepeatCount(-1);
//给控件设置动画
mTv.startAnimation(animation);
}
1.3 AlphaAnimation(透明度)
/**
* 创建透明度渐变动画
*/
private void createAlphaAnimation() {
/***
* 构造方法如下
* fromAlpha、toAlpha表示透明度的起始值和结束值,0.0f表示全透明,1.0f表示不透明。
* public AlphaAnimation(float fromAlpha, float toAlpha) {}
*/
//初始化AlphaAnimation
AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);
//动画执行时间 animation.setDuration(2000);
//动画重复次数-1表示不停重复
//animation.setRepeatCount(-1);
//给控件设置动画
mTv.startAnimation(animation);
}
1.4 TranslateAnimation(位移)
/**
* 创建位移动画
*/
private void createTranslateAnimation() {
/**
* 构造方法如下
* fromXType、toXType、fromYType、toYType(Animation.ABSOLUTE,、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENT)
* 当type为Animation.ABSOLUTE时,这个个值为具体的像素值,当type为Animation.RELATIVE_TO_SELF或Animation.RELATIVE_TO_PARENT,这个个值为比例值,取值范围是[0f, 1.0f]
*public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,int fromYType, float fromYValue, int toYType, float toYValue) {}
*/
TranslateAnimation animation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f,
Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f, Animation.ABSOLUTE, 100);
animation.setDuration(2000);
//动画重复次数-1表示不停重复
//animation.setRepeatCount(-1);
//动画结束后View停留在结束位置
//animation.setFillAfter(true);
mTv.startAnimation(animation); }
1.5 AnimationSet(组合)
/** * 创建组合动画
*/
private void createAnimationSet(){
AnimationSet animationSet = new AnimationSet(true);
AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.0f);
ScaleAnimation scaleAnimation = new ScaleAnimation(1f, 0.5f, 1f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
TranslateAnimation translateAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f, Animation.RELATIVE_TO_SELF, 0f, Animation.ABSOLUTE, 100); animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(rotateAnimation);
animationSet.addAnimation(translateAnimation);
animationSet.setDuration(2000);
animationSet.setRepeatCount(-1);
mTv.startAnimation(animationSet);}
AnimationSet animationSet = new AnimationSet(true); true表示这个组合动画公用一个插值器,插值器的概念和使用方法,我会在文章的末尾进行说明。
第二种:使用xml创建,在res下创建anim文件夹,如图:
alpha_demo.xml:
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="2000">
</alpha>
</rotate>
rotate_demo.xml:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360">
</rotate>
scale_demo.xml:
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="1.0"
android:toXScale="0.5"
android:fromYScale="1"
android:toYScale="0.5"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2000">
</scale>
translate_demo.xml:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="0"
android:fromYDelta="0"
android:toYDelta="100"
android:duration="2000">
</translate>
set_demo.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000" >
<scale
android:fromXScale="1"
android:fromYScale="1"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.5"
android:toYScale="0.5" />
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360"/>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="100"/>
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.1"/>
</set>
效果图:
2.帧动画
帧动画帧动画顾名思义,一帧一帧播放的动画就是帧动画。 帧动画和我们小时候看的动画片的原理是一样的,在相同区域快速切换图片给人们呈现一种视觉的假象感觉像是在播放动画,其实不过是多张图片在一帧一帧的切换罢了。切记,图片不易过多过大,不然容易产生OOM。
先在drawble下新建一个xml:
frame_animation.xml:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
//oneshot属性表示是否循环播放,值为true则只播放一次。
<item android:drawable="@mipmap/animation1" android:duration="200"/>
<item android:drawable="@mipmap/animation2" android:duration="200"/>
<item android:drawable="@mipmap/animation3" android:duration="200"/>
<item android:drawable="@mipmap/animation4" android:duration="200"/>
<item android:drawable="@mipmap/animation5" android:duration="200"/>
<item android:drawable="@mipmap/animation6" android:duration="200"/>
<item android:drawable="@mipmap/animation7" android:duration="200"/>
<item android:drawable="@mipmap/animation8" android:duration="200"/>
</animation-list>
java代码:
/**
* 帧动画
*/
public class FrameAnimation extends AppCompatActivity {
@Bind(R.id.img)
ImageView mImg;
@Bind(R.id.btn1)
Button mBtn1;
@Bind(R.id.btn2)
Button mBtn2;
AnimationDrawable animationDrawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frame_animation);
ButterKnife.bind(this);
mImg.setImageResource(R.drawable.frame_animation);
animationDrawable = (AnimationDrawable) mImg.getDrawable();
}
@OnClick({R.id.btn1, R.id.btn2})
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn1:
animationDrawable.start();
break;
case R.id.btn2:
animationDrawable.stop();
break;
}
}}
效果如下:
3.属性动画
在Android3.0之后才引进的,属性动画改变的是对象的实际属性,如ImageView的缩放,ImageView的位置与大小属性值都改变了。属性动画不止可以应用于View,还可以应用于任何对象。属性动画只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。ValueAnimator和ObjectAnimator是属性动画的两个核心类。
3.1 ValueAnimator:对一个范围内的值进行一个平滑的动画过渡效果
下面的动画是在2s内实现从100到50的一个动画,然后每次更新获取到值后进行你要的操作,我是这么做的:
private void createValueAnimator() {
//初始化ValueAnimator
ValueAnimator valueAnimator = ValueAnimator.ofInt(100, 80);
//监听动画
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int value = (int) animation.getAnimatedValue();//当前的值
mImg.getLayoutParams().width = value;
mImg1.getLayoutParams().height = value;
mImg.requestLayout();
}
});
valueAnimator.setDuration(2000);//动画时长
valueAnimator.start();//启动动画}
除了ValueAnimator.ofInt(),常用的还有ValueAnimator.ofFloat()、ValueAnimator.ofArgb(),ValueAnimator.ofFloat()是实现浮点数的平滑过渡,用法跟ValueAnimator.ofInt()差不多是一样的,那我们看看ValueAnimator.ofArgb(),实现颜色值的过渡,举个例子:
private void vreateValueAnimatorArgb(){
//ValueAnimator.ofArgb()方法是在API Level 21中才加入的
if(Build.VERSION.SDK_INT >= 21){
ValueAnimator valueAnimator = ValueAnimator.ofArgb(R.color.red,R.color.blue);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int color = (int) animation.getAnimatedValue();
mImg.setBackgroundResource(color);
mImg.requestLayout();
Log.d("AAA",color+"");
}
});
valueAnimator.setDuration(2000);//动画时长
valueAnimator.start();//启动动画
}}
3.2 ObjectAnimator 对任意对象的属性进行动画操作,那么,ObjectAnimator肯定是可以实现补间动画的效果咯,注意,要设置的对象的属性,必须要有set方法,不然不起作用的。
举一个例子,我们设置一个对象的缩放动画:
ObjectAnimator animator = ObjectAnimator.ofFloat(mImg, "scaleX", 1f, 2f);
animator.setDuration(2000);
animator.start();
这里我们设置对象的属性为scaleX,表示这个动画执行的时候,会在水平方向将mImg(mImg是个ImageView)的宽度拉伸两倍,由于mImg这个对象没有setScale()这个方法,所以这里就不能设置属性为"scale",这样是没有效果的。同样,我们也可以设备对象的旋转、透明度、平移的动画,只需要修改对象的属性就可以了,这里就不再举例。
3.3 跟补间动画类似,属性动画也可以将多个动画组合在一起执行,如果多个动画同时执行,则调用animatorSet.playTogether(),如果动画执行的先后顺序不一样,则通过animatorSet.play()获得一个AnimatorSet.Builder对象,这个对象有四个方法:
after(Animator anim) 将现有动画插入到传入的动画之后执行
after(long delay) 将现有动画延迟指定毫秒后执行
before(Animator anim) 将现有动画插入到传入的动画之前执行
with(Animator anim) 将现有动画和传入的动画同时执行
AnimatorSet animatorSet = new AnimatorSet();
ObjectAnimator alpha = ObjectAnimator.ofFloat(view, "alpha", 1f, 0f, 1f);
ObjectAnimator rotation = ObjectAnimator.ofFloat(view, "rotation", 0f, 360f);
ObjectAnimator translation = ObjectAnimator.ofFloat(view, "translationX", 400f, 0f);
ObjectAnimator scale = ObjectAnimator.ofFloat(view, "scaleX", 1f, 2f, 1f);
animatorSet.playTogether(alpha,rotation,translation,scale);//动画同时执行
//如果不同时执行,则如下,根据自己的需求可以自己调整
//animatorSet.play(alpha).with(translation).after(rotation).before(scale);
animatorSet.setDuration(5000);animatorSet.start();
3.4 跟补间动画一样,属性动画也可以使用xml的方式,在res下创建animator文件夹,如下:
可以使用的标签有<animator>、<objectAnimator> 和<set>,分别表示ValueAnimator、ObjectAnimator和AnimatorSet。比如上面我们用ObjectAnimator实现的旋转动画,用xml来写的话就是酱紫的:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:propertyName="rotation"
android:valueFrom="0"
android:valueTo="360"
android:valueType="floatType" />
<animator>和<set>标签就不举例啦,使用方法都是大同小异,大家多写几遍就会了,最后我们看一下在代码中如何使用这个xml:
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.anim_test); //anim_test就是我们写的xml文件
animator.setTarget(view); //view表示我们要设置动画的对象
animator.start();
3.5属性动画也可以监听动画执行的状态,有两种方式,可以根据自己的需要选择,代码如下:
第一种:
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) { }
@Override
public void onAnimationEnd(Animator animation) { }
@Override
public void onAnimationCancel(Animator animation) { }
@Override
public void onAnimationRepeat(Animator animation) { }
});
第二种
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
}
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
}
});
简单看一下效果(有点丑,哈哈!!!):
3.6 最后补充一下插值器的概念,所谓的插值器,就是我们执行的动画速度的改变规律,常用的插值器有以下几LinearInterpolator(匀速)、AccelerateInterpolator(加速)、AccelerateDecelerateInterpolator(先加速再减速)、BounceInterpolator(反弹数次后停止)、DecelerateInterpolator(减速),我们在代码或者xml中都可以使用插值器。
java代码中使用插值器:
RotateAnimation animation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(2000);
animation.setInterpolator(new LinearInterpolator());//设置一个匀速的插值器
mTv.startAnimation(animation);
xml中使用插值器:
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:interpolator="@android:anim/linear_interpolator"
android:toDegrees="360">
</rotate>
最后看一下这5中插值器的效果,就拿上面的补间动画修改一下好了,效果如下: