在Api11(android3.0)之前,动画分两类:补间动画(Tween Animation)和帧动画(Frame Animation)
Api11(Android3.0)新加入了属性动画,动画分类:
1>View动画(补间动画)
2> 帧动画【其实帧动画也可归为View动画之一】
3>属性动画
View动画
view动画通过对场景里的对象不断做图像变换(平移[translate]、旋转[rotate]、缩放[scale]、透明度[alpha])从而产生动画效果,它是一种渐近式动画,并且view动画支持自定义。
View动画的四种变换效果对应着Animation的四个类:TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnomation--->对应标签分别:<translate>、<scale>、<rotate>、<alpha>
view动画四种变换
名称 | 标签 | 子类 | 效果 |
平移动画 | <translate> | TranslateAnimation | 移动view |
缩放动画 | <scale> | ScaleAnimation | 放大或缩小view |
旋转动画 | <rotate> | RotateAnimation | 旋转view |
透明度动画 | <alpha> | AlphaAnomation | 改变view的透明度 |
这四种动画可以通过xml来定义,也可以通过代码来动态创建【对于View动画来说,用xml定义比较方便些,可读性比较好】
好了,那就先来了解一下view动画的一些属性:
<set>表示动画集合,对应AnimationSet集合类,它可以包含若干个动画,并且它的内部是可以嵌套其他动画集合的,它的两个属性含义如下:
android:interpolator表示动画集合所采用的插值器,插值器影响动画的速度,比如非匀速动画就需要通过插值器来控制动画的播放过程。这个属性可以不指定,默认@android:anim/accelerate_decelerate_interpolator,即加速减速插值器。Accelerate_Decelerate_Interpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速(加速减速插值器:动画两头慢中间快) Decelerate_Interpolator 在动画开始的地方快然后慢(减速插值器:动画越来越慢) Accelerate_Interpolator 在动画开始的地方速率改变比较慢,然后开始加速(加速插值器:动画越来越快) Linear_Interpolator 以常量速率改变(线性插值器:匀速动画) Anticipate_Interpolator 开始的时候向后然后向前甩 Anticipate_Overshoot_Interpolator 开始的时候向后然后向前甩一定值后返回最后的值 Bounce_Interpolator 动画结束的时候弹起 Cycle_Interpolator 动画循环播放特定的次数,速率改变沿着正弦曲线 Overshoot_Interpolator 向前甩一定值后再回到原来位置
android:shareInterpolator
表示集合中的动画是否和集合共享同一个插值器,如果集合不指定插值器,那么子动画就需要单独指定所需的插值器或者使用默认值
一些属性介绍:
fromXDelta:动画起始时 X坐标上的移动位置
toXDelta:动画结束时 X坐标上的移动位置
fromYDelta:动画起始时Y坐标上的移动位置
toYDelta:动画结束时Y坐标上的移动位置
fromDegrees:旋转偏移的开始角度
toDegrees:旋转偏移的结束角度
pivotXType:指定X轴的旋转模式,可以取值Animation.ABSOLUTE(直接以屏幕为像素单位),
Animation.RELATIVE_TO_SELF(以自身为参照物),Animation.RELATIVE_TO_PARENT(相对于父容器)。
pivotXValue:指定旋转中心距离父容器左顶点的X距离
pivotYType:指定Y轴的旋转模式,可以取值Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,Animation.RELATIVE_TO_PARENT。
pivotYValue:指定旋转中心距离父容器上顶点的Y距离
fromAlpha:开始的透明度(1表示完成不透明,0表示完全透明)
toAlpha: 结束的透明度
fromXScale:动画起始时 X坐标上的伸缩尺寸
toXScale:动画结束时 X坐标上的伸缩尺寸
fromYScale:动画起始时Y坐标上的伸缩尺寸
fromYScale:动画结束时Y坐标上的伸缩尺寸
pivotXType:指定X轴的伸缩模式,可以取值Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,Animation.RELATIVE_TO_PARENT。
pivotXValue:动画相对于物件的X坐标的开始位置
pivotYType:指定Y轴的伸缩模式,可以取值Animation.ABSOLUTE,Animation.RELATIVE_TO_SELF,Animation.RELATIVE_TO_PARENT。
pivotYValue:动画相对于物件的Y坐标的开始位置
下面来看一个怎样用xml方式实现:
创建好后来编辑一下文件内容,【当然这几种变换方式可以单独使用也可以混合使用】
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
>
<translate
android:duration="100"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100"
android:toYDelta="100"
android:interpolator="@android:anim/linear_interpolator"
/>
<alpha
android:duration="100"
android:fromAlpha="1"
android:toAlpha="0"
/>
</set>
再在布局文件创建一个button
<Button
android:id="@+id/tran"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="动画测试"/>
最后在Activity中引入动画xml文件并启动
Animation animation= AnimationUtils.loadAnimation(this,R.anim.viewanim);
tranButton.startAnimation(animation);
ok,这样就实现了!!!
上面使用xml文件来加载的,当然也可以用java代码来实现
AlphaAnimation alphaAnimation=new AlphaAnimation(1,0);
alphaAnimation.setFillAfter(true);
alphaAnimation.setDuration(100);
tranButton.startAnimation(alphaAnimation);
view动画也可以用户Activity之间切换效果:
Activity本本身有默认的切换效果,当然我们也可以自定义来实现,主要用到下面这个方法:
overridePendingTransition(int enterAnim,int exitAnim),这个方法必须在startActivity(intent)或者finish()之后被调用才能生效
当Activity启动时,添加自定义切换效果
Intent intent=new Intent(this,TranActivity.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);
}
例如:让Activity切换时呈现淡入淡出效果
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
>
<alpha
android:duration="1000"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
/>
</set>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
>
<alpha
android:duration="1000"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:interpolator="@android:anim/decelerate_interpolator"
/>
</set>
然后再在Activity中引入即可!
View动画还可以在ViewGroup中控制子元素的出场效果
帧动画
帧动画是通过顺序播放一系列图像从而产生动画效果,如果图片过多或者过大易导致OOM。
下面来看下怎样实现帧动画:
首先在drawable文件夹下创建frame.xml文件
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<!--oneshot代表着是否只展示一遍,设置为false会不停的循环播放动画 -->
<item android:drawable="@mipmap/p1" android:duration="100"></item>
<item android:drawable="@mipmap/p2" android:duration="100"></item>
<item android:drawable="@mipmap/p3" android:duration="100"></item>
<item android:drawable="@mipmap/p4" android:duration="100"></item>
<item android:drawable="@mipmap/p5" android:duration="100"></item>
<item android:drawable="@mipmap/p6" android:duration="100"></item>
<item android:drawable="@mipmap/p7" android:duration="100"></item>
<item android:drawable="@mipmap/p8" android:duration="100"></item>
<item android:drawable="@mipmap/p9" android:duration="100"></item>
</animation-list>
设置布局文件两个Button按钮和一个ImageView
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="startAnimation"
android:text="开始"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="stopAnimation"
android:text="停止"
/>
<!--android:background="@drawable/frame"-->
<ImageView
android:id="@+id/my_img"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
最后在Activity加载资源文件
private ImageView imageView;
private AnimationDrawable drawable;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView=(ImageView) MainActivity.this.findViewById(R.id.my_img);
imageView.setBackgroundResource(R.drawable.frame);
drawable=(AnimationDrawable) imageView.getBackground();
}
//开始
public void startAnimation(View view){
drawable.start();
}
//停止
public void stopAnimation(View view){
drawable.stop();
}
好了,帧动画比较简单一点,但是使用时要注意片过多或者过大易导致OOM。
属性动画
属性动画是通过动态地改变对象的属性。一般情况下,所有补间动画的内容,都可以通过属性动画实现。
比较常用的几个动画类:ValueAnimator、ObjectAnimator、AnimatorSet(动画集合),其中ObjectAnimator继承ValueAnimator
类与标签对应关系
类 | 标签 |
ValueAnimator | <animator> |
ObjectAnimator | <objectAnimator> |
AnimatorSet | <set> |
下面举几个简单的例子:
1>让一个button在3秒内,从常规变为全透明,再从全透明变为常规状态
ObjectAnimator animator=ObjectAnimator.ofFloat(tranButton,"alpha",1f,0f,1f);
animator.setDuration(3000);
animator.start();
2>
改变一个对象的背景色属性,典型的情形是改变View的背景色
ValueAnimator valueAnimator=ObjectAnimator.ofInt(tranButton,"backgroundColor",0xFFFF8080,0xFF8080FF);
valueAnimator.setDuration(3000);
valueAnimator.setEvaluator(new ArgbEvaluator());
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);//无限重复
valueAnimator.setRepeatMode(ValueAnimator.RESTART);//重复模式:反向
valueAnimator.start();
3>
AnimatorSet,5秒之内对view进行平移、旋转、缩放、透明度改变
AnimatorSet set=new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(tranButton,"rotationX",0,360),
ObjectAnimator.ofFloat(tranButton,"rotationY",0,180),
ObjectAnimator.ofFloat(tranButton,"rotation",0,-90),
ObjectAnimator.ofFloat(tranButton,"translationX",0,90),
ObjectAnimator.ofFloat(tranButton,"translationY",0,90),
ObjectAnimator.ofFloat(tranButton,"scaleX",1,1.5f),
ObjectAnimator.ofFloat(tranButton,"scaleY",1,0.9f),
ObjectAnimator.ofFloat(tranButton,"alpha",1,0.2f,1f)
);
set.setDuration(5000).start();
当然除了用代码实现之外,也可以用xml文件来实现:
在res/下创建animator文件夹
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="together">
<!--together:表示集合中的子动画同时播放
sequentially:表示集合中的子动画按照前后顺序依次播放
-->
<objectAnimator
android:duration="2000"
android:valueFrom="-500"
android:valueTo="0"
android:propertyName="translationX"
android:valueType="floatType"
/>
</set>
Animator animator = AnimatorInflater.loadAnimator(MainActivity.this,R.animator.test_file);
animator.setTarget(tranButton);
animator.start();
好了,两种方式都已介绍完毕,但在实际开发中还是用代码来实现比较简单、方便些,因为有些时候属性的起始值可能不确定,用代码实现会灵活些!!!
附:一些属性介绍:
android:propertyName 表示属性动画作用对象的属性名称
android:valueType 表示propertyName 所指定的属性类型,有intType(整型)、floatType(浮点型)两个类型,但是如果propertyName指定的属性名表示颜色,则不用指定valueType,系统会自动处理
android:valueFrom 表示属性的起始值
android:valueTo 表示属性的结束值
android:duration 动画的时长
android:startOffset 表示动画的延迟时间,动画开始后,需要延迟多少毫秒之后才会真正执行播放android:repeatCount 表示动画的重复次数---默认值为0,-1表示无限循环/"infinite":表示无限循环android:repeatMode 表示动画的重复模式--- 值"reverse":表示反向 "restart":表示重新启动属性动画的监听器
使用监听器监听动画的播放过程,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。
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); } });
动画使用的一些注意事项:1>帧动画,当图片数量过且图片较大时,易OOM2>View动画是对View的影像做动画,View的真正状态并没有改变,因此有时候会出现动画完成后View无法隐藏,即setVisbility(View.GONE)失效了,这时只用调用view.clearAnimation()清除View动画即可解决3>属性动画有一类无限循环的动画,这类动画要在Activity退出时及时停止,否则将导致Activity无法释放。view动画不存在这个问题