一个没有动画的应用是没有灵魂的应用。
Android中的动画大致可以分为三类:逐帧动画 补间动画和属性动画
一、逐帧动画
逐帧动画就是让一些静态的图片顺序播放,利用人的视觉暂留,实现动画。
逐帧动画的基本使用如下:
逐帧动画通常是采用 XML 资源进行定义的,需要在 <animation-list .../> 标签下使用 <item .../> 子元素标签定义动画的全部帧,并指定各帧的持续时间。 定义逐帧动画的语法格式如下:
<?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/first" android:duration="200"/>
<item android:drawable="@drawable/second" android:duration="200"/>
<item android:drawable="@drawable/third" android:duration="200"/>
<item android:drawable="@drawable/fourth" android:duration="200"/>
</animation-list>
android:oneshot="true"用来表示是否动画循环播放,true表示不循环播放。
每个item是每一个静态图片 duration是持续的时间。使用的时候作为控件的背景使用即可。
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/iv_show_center"
android:background="@drawable/frame_animation"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
逐帧动画对应一个AnimationDrawable类
//获取AnimationDrable对象
mAnimationDrawable = (AnimationDrawable) ivShow.getBackground();
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.bt_start:
mAnimationDrawable.start();
break;
case R.id.bt_stop:
mAnimationDrawable.stop();
break;
}
调用开始结束就可以实现逐帧动画的播放。
二、补间动画
补间动画类似于指定开始帧跟结束帧,让系统自动计算实现中间的变换,也被称为View动画。
View动画的四种变换效果对应着Animation的四个子类:TranslateAnimation、ScaleAnimation、RotateAnimation、AlphaAnimation。四种动画可以用这四个类通过代码实现,也可以使用XML文件来定义。建议使用XML来定义动画,因为XML格式可读性好而且方便复用。
名称 | 标签 | 子类 |
---|---|---|
平移动画 | <translate/> | TranslateAnimation |
缩放动画 | <scale/> | ScaleAnimation |
旋转动画 | <rotate/> | RotateAnimation |
透明度动画 | <alpha/> | AlphaAnimation |
View动画可以是单个动画,也可以是多个动画的组合实现
动画属性:
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0" //x的起始值
android:fromYDelta="0"
android:toXDelta="100" //x的结束值
android:toYDelta="100">
</translate>
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="0.0" //缩放的起始值
android:fromYScale="0.0"
android:pivotX="50%" //缩放的轴点 取值类型有三种:数字;百分比;百分比+”p”;
android:pivotY="50%"
android:toXScale="2.0"
android:toYScale="2.0"
android:duration="1000"> //持续的时间
</scale>
-
数字:例如50.0,这里的单位是px像素
-
百分比:例如50%,这里是相对于自己控件宽度的百分比,实际的值是mIvImg.getWidth()*50%;
-
百分比+”p”:例如50%p,这里是表示相对于自己控件的父控件的百分比,
<?xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:fromDegrees="0" //起始的旋转度数 android:toDegrees="360" android:pivotY="50%" android:pivotX="50%" android:duration="1000"> </rotate> <?xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:fromAlpha="1.0" //不透明 android:toAlpha="0.5" //0 表示完全透明 android:duration="2000" android:interpolator="@android:anim/accelerate_decelerate_interpolator"> </alpha>
一般是组合起来使用
<?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="2000"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:toAlpha="0.5">
</alpha>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="360" />
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:repeatMode="reverse"
android:toXScale="2.0"
android:toYScale="2.0" />
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100"
android:toYDelta="100">
</translate>
</set>
一般是对应一个 Animation类,使用AnimationUtils来使用。
mAnimation = AnimationUtils.loadAnimation(this, R.anim.all_animal);
mAnimation.setFillAfter(true);//动画结束后保留结束状态
当然一般是建议放在xml文件里,以便后期的复用。但是使用在java问件里也可以写:
如下:
//移动
Animation mTranslateAnimation=new TranslateAnimation(0,500,0,500);
mTranslateAnimation.setDuration(2000);
btEnd.startAnimation(mTranslateAnimation);
//缩放
Animation mScaleAnimation =new ScaleAnimation(0,2,0,2);
mScaleAnimation.setDuration(2000);
btEnd.startAnimation(mScaleAnimation);
//旋转
Animation mRotateAnimation =new RotateAnimation(0,270);
mRotateAnimation.setDuration(200);
btEnd.startAnimation(mRotateAnimation);
//透明度
Animation mAlphaAnimation =new AlphaAnimation(1,0);
mAlphaAnimation.setDuration(2000);
btEnd.startAnimation(mAlphaAnimation);
三、属性动画
属性动画从 API 11 才有,属性动画可以对任意对象的属性进行动画而不仅仅是View,达到的效果是:在一个时间间隔内完成对象从一个属性值到另一个属性值的改变。属性动画常用的动画类:ValueAnimator、ObjectAnimator、AnimatorSet。ObjectAnimator继承自ValueAnimator,AnimatorSet是动画集合。 属性动画也有对应的xml标签,但是建议使用代码来实现属性动画,因为使用代码比xml简单。而且很多时候一个属性的起始值无法提前确定。
看一下在代码中的使用:
AnimatorSet set = new AnimatorSet();
set.playTogether(
ObjectAnimator.ofFloat(myView, "rotationX", 0, 360),
ObjectAnimator.ofFloat(myView, "rotationY", 0, 180),
ObjectAnimator.ofFloat(myView, "rotation", 0, -90),
ObjectAnimator.ofFloat(myView, "translationX", 0, 90),
ObjectAnimator.ofFloat(myView, "translationY", 0, 90),
ObjectAnimator.ofFloat(myView, "scaleX", 1, 1.5f),
ObjectAnimator.ofFloat(myView, "scaleY", 1, 0.5f),
ObjectAnimator.ofFloat(myView, "alpha", 1, 0.25f, 1)
);
set.setDuration(5*1000).start();
插值器简介:
java 类 | xml描述 | 说明 |
---|---|---|
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolato | 动画始末速率较慢,中间加速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 动画开始速率较慢,之后慢慢加速 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 开始的时候从后向前甩 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 类似上面AnticipateInterpolator |
BounceInterpolator | @android:anim/bounce_interpolator | 动画结束时弹起 |
CycleInterpolator | @android:anim/cycle_interpolator | 循环播放速率改变为正弦曲线 |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 动画开始快然后慢 |
LinearInterpolator | <u></u>@android:anim/linear_interpolator | 动画匀速改变 |
OvershootInterpolator | @android:anim/overshoot_interpolator | 向前弹出一定值之后回到原来位置 |
四、动画使用注意事项
可能导致的问题
oom问题
主要出现在帧动画中
内存泄漏
属性动画中存在类似的问题
兼容性问题
某些特殊的使用场景 不同android系统
View动画的问题
view动画是对view的影像做动画,并不是真正的改变view的状态,有时候会出现view无法隐藏的问题,GONE不掉,记得此时可以先调用view.clearAnimation()清除动画在GONE
不要使用px
尽量使用dp
动画元素的交互
Android3.0 属性动画的单机事件触发位置为移动后的位置,但是View动画仍在原来的位置。
硬件加速
app中动画较多的时候,建议开启硬件加速。
Application 或者Activity里加属性
android:hardwareAccelerated="true"
判断的方法
canvas.isHardwareAccelerated();// returns true if the Canvas is hardware accelerated