http://blog.csdn.net/dmk877/article/details/51912104
1 补间(Tween)动画
定义补间动画思路:
设置一张图片的开始状态(包括透明度、位置、缩放比、旋转度),并设置该图片的结束状态(包括透明度、位置、缩放比、旋转度),再设置动画的持续时间。
定义动画的XML资源放在/res/anim/路径下,需自行创建该路径。
假设动画显示在ImageView下:
1.1 res/anim目录下添加动画
定义AnimationDrawable资源需指定4个元素:
-
alpha: 设置透明度的改变。
-
scale: 设置图片进行缩放变换。
-
translate: 设置图片进行位移变换。
-
rotate: 设置图片进行旋转。
<set xmlns:android=”http://schemas.android.com/apk/res/android”
android:fillAfter=["true" | "false"]
android:fillBefore=["true" | "false"]
android:fillEnabled["true" | "false"]
android:repeatMode=["reverse" | "restart"]
android:repeatCount="重复播放次数"
android:interpolator=”@[package:]anim/interpolator_resource”
android:shareInterpolator=["true" | "false"]
android:duration="持续时间"
android:startOffset="动画多少毫秒后开始">
<alpha
android:fromAlpha=”float”
android:toAlpha=”float”/>
<scale
android:fromXScale=”float”
android:toXScale=”float”
android:fromYScale=”float”
android:toYScale=”float”
android:pivoX=”float”
android:pivoY=”float”/>
<translate
android:fromXDelta=”float”
android:toXDelta=”float”
android:fromYDelta=”float”
android:toYDelta=”float”/>
<rotate
android:fromDegrees=”float”
android:toDegrees=”float”
android:pivoX=”float”
android:pivoY=”float”/>
</set>
总体说明:
-
fromXxx、toXxx属性定义图片的开始状态、结束状态。
-
scale和rotate元素需要指定pivoX、pivoY属性来指定scale的“中心点”、rotate的“旋轴点”。
-
interpolator属性指定动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等,Android系统的R.main类中包含了大量常量定义动画速度:
-
linear_interpolator: 匀速变换。
-
accelerate_interpolator: 加速变换。
-
decelerate_interpolator: 减速变换。
-
想让 <set…/>
元素下所有的变换效果使用相同的动画速度,指定 android:shareInterpolator=”true”
。
详细说明:
通用属性说明(无论在 <set/>
还是 <alpha/>
其他动画标签都适用)
-
fillAfter:动画执行完成,是否停留在最后一帧(保持动画完成后的状态)
-
fillBefore:动画执行完成,是否还原到开始动画前状态;fillEnable为true时才有意义,否则默认为true
-
fillEnabled:动画执行完成,是否还原到开始动画前状态
-
repeatMode:动画执行完成后的状态(reverse:倒序回放,restart:重新播放一遍);与repeatCount联合使用设置重复播放类型;repeatMode只适用于单个动画,不适合
<set/>
-
repeatCount:动画重复次数
-
interpolator:动画的变化速度,可以实现匀速、正加速、负加速、无规则变加速等,Android系统的R.main类中包含了大量常量定义动画速度:
-
linear_interpolator: 匀速变换。
-
accelerate_interpolator: 加速变换。
-
decelerate_interpolator: 减速变换。
-
系统提供的常用interpolator如下:
interpolator对象 | 资源id | 功能 |
---|---|---|
AccelerateDecelerateInterpolator | @android:anim/accelerate_decelerate_interpolator | 先加速后减速 |
AccelerateInterpolator | @android:anim/accelerate_interpolator | 加速 |
AnticipateInterpolator | @android:anim/anticipate_interpolator | 先回退一小步然后加速前进 |
AnticipateOvershootInterpolator | @android:anim/anticipate_overshoot_interpolator | 先回退一小步然后加速前进,超出终点一小步后再回到终点 |
BounceInterpolator | @android:anim/bounce_interpolator | 最后阶段弹球效果 |
CycleInterpolator | @android:anim/cycle_interpolator | 周期运动 |
DecelerateInterpolator | @android:anim/decelerate_interpolator | 减速 |
LinearInterpolator | @android:anim/linear_interpolator | 匀速 |
OvershootInterpolator | @android:anim/overshoot_interpolator | 快速到达终点并超出一小步最后回到终点 |
自定义Interpolator需要在res/anim新建xml,设置对应的interpolator标签修改相应属性
自定义Interpolator可调整属性:
标签 | 属性 |
---|---|
<accelerateDecelerateInterpolator> | 无 |
<accelerateInterpolator> | android:factor 浮点值,加速速率,默认为1 |
<anticipateInterpolator> | android:tension 浮点值,起始点后退的张力、拉力数,默认为2 |
<anticipateOvershootInterpolator> | android:tension 浮点值,起始点后退的张力、拉力数,默认为2;android:extraTension 浮点值,拉力的倍数,默认为1.5(2 * 1.5) |
<bounceInterpolator> | 无 |
<cycleInterpolator> | android:cycles 整数值,循环的个数,默认为1 |
<decelerateInterpolator> | android:factor 浮点值,减速的速率,默认为1 |
<linearInterpolator> | 无 |
<overshootInterpolator> | android:tension 浮点值,超出终点后的张力、拉力,默认为2 |
-
shareInterpolator:使用相同的动画速度(一般使用在操作多个动画使用)
-
duration:动画时长
-
startOffset:动画在多少毫秒后才开始
某些动画值的设置:
可以是数值、百分数、百分数p;以水平方向为例,数值50,表示当前View的左上角(作为原点)在x轴方向(从左往右)50px作为起始坐标;
百分数50%,表示当前View的左上角在x轴方向以View宽度的50%作为起始坐标;百分数p为50%p,表示当前View的左上角在x轴方向以View的父View宽度的50%作为起始坐标。
-
alpha
- fromAlpha:动画开始时的透明度,范围为0.0-1.0,0.0完全透明,1.0完全不透明
- toAlpha:动画结束时的透明度,范围为0.0-1.0,0.0完全透明,1.0完全不透明
-
scale
-
fromXScale:起始的x方向上相对自身的缩放比例,比如1.0自身无变化,0.5缩小一倍,2.0放大一倍
-
toXScale:结尾的x方向上相对自身的缩放比例,比如1.0自身无变化,0.5缩小一倍,2.0放大一倍
-
fromYScale:起始的y方向上相对自身的缩放比例,比如1.0自身无变化,0.5缩小一倍,2.0放大一倍
-
toYScale:结尾的y方向上相对自身的缩放比例,比如1.0自身无变化,0.5缩小一倍,2.0放大一倍
-
pivoX:缩放起点x坐标,可以是数值、百分数、百分数p
-
pivoY:缩放起点y坐标,可以是数值、百分数、百分数p
-
-
translate
-
fromXDelta:起始点x轴坐标,可以是数值、百分数、百分数p
-
toXDelta:结束点x轴坐标,可以是数值、百分数、百分数p
-
fromYDelta:起始点y轴坐标,可以是数值、百分数、百分数p
-
toYDelta:结束点y轴坐标,可以是数值、百分数、百分数p
-
-
rotate
-
fromDegrees:起始的旋转角度
-
toDegrees:结束的旋转角度(注意是结束的旋转角度,即停留的角度,不是要旋转的角度)
-
pivoX:旋转起点x坐标,可以是数值、百分数、百分数p
-
pivoY:旋转起点的y坐标,可以是数值、百分数、百分数p
-
1.2 代码添加动画
- alpha
AlphaAnimation aa = new AlphaAnimation(开始的透明度,结束时的透明度);
- rotate
RotateAnimation ra = new RotateAnimation(开始的角度,旋转的角度);
- scale
ScaleAnimation sa = new ScaleAnimation(x轴开始大小,x轴最终大小,y轴开始大小,y轴最终大小);
- translate
TranslateAnimation ta = new TranslateAnimation(x轴开始坐标,x轴最终坐标,y轴开始坐标,y轴最终坐标);
1.3 加载动画
Animation animation = AnimationUtils.loadAnimation(Context,资源id);
1.4 开启动画
imageView.startAnimation(开启的动画对象);
1.5 组合动画
[1]AnimationSet set = new AnimationSet(false);
set.addAnimation(动画对象);
…………
[2]加载动画
[3]开启动画
anim目录下:
- alpha.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 设置View从完全透明到完全不透明 -->
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:fillAfter="true"
android:duration="1000"/>
- rotate.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 设置从0旋转360度,旋转中心点是View的中心 -->
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true"/>
- scale.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 设置了水平和垂直坐标从View的两倍开始缩放到自身大小 -->
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXScale="2.0"
android:toXScale="1.0"
android:fromYScale="2.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="1000"
android:fillAfter="true"/>
- translate.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 设置View水平平移自身位置大小的距离 -->
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0"
android:toXDelta="50%"
android:fromYDelta="0"
android:toYDelta="0"
android:duration="1000"
android:fillAfter="true"/>
- set.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- View从缩放点0开始扩大到自身大小,伴随着旋转360度和从完全透明到完全不透明,
以上三种动画执行完成后,开始平移View自身一半大小后,再从完全不透明到完全透明-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<rotate
android:fromDegrees="0.0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="3000"/>
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="3000"/>
<scale
android:fromXScale="0.0"
android:toXScale="1.0"
android:fromYScale="0.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:duration="3000"/>
<translate
android:startOffset="3000"
android:fromXDelta="0.0"
android:toXDelta="50%"
android:duration="1000"/>
<alpha
android:startOffset="4000"
android:fromAlpha="1.0"
android:toAlpha="0.0"
android:duration="1000"/>
</set>
public class TweenAnimActivity extends AppCompatActivity {
private static final int ANIM_TYPE_ALPHA = 0;
private static final int ANIM_TYPE_SCALE = 1;
private static final int ANIM_TYPE_TRANSLATE = 2;
private static final int ANIM_TYPE_ROTATE = 3;
private static final int ANIM_TYPE_SET = 4;
private int mCurrentAnimType;
private ImageView mIvAnim;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tween_anim);
mIvAnim = findViewById(R.id.iv_anim);
findViewById(R.id.btn_alpha).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCurrentAnimType = ANIM_TYPE_ALPHA;
doAnim(ANIM_TYPE_ALPHA, 0);
}
});
findViewById(R.id.btn_scale).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCurrentAnimType = ANIM_TYPE_SCALE;
doAnim(ANIM_TYPE_SCALE, 0);
}
});
findViewById(R.id.btn_translate).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCurrentAnimType = ANIM_TYPE_TRANSLATE;
doAnim(ANIM_TYPE_TRANSLATE, 0);
}
});
findViewById(R.id.btn_rotate).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCurrentAnimType = ANIM_TYPE_ROTATE;
doAnim(ANIM_TYPE_ROTATE, 0);
}
});
findViewById(R.id.btn_set).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mCurrentAnimType = ANIM_TYPE_SET;
doAnim(ANIM_TYPE_SET, 0);
}
});
findViewById(R.id.btn_repeat_reverse).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
doAnim(mCurrentAnimType, Animation.REVERSE);
}
});
findViewById(R.id.btn_repeat_restart).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
doAnim(mCurrentAnimType, Animation.RESTART);
}
});
}
private void doAnim(int animType, int repeatMode) {
int animRes;
switch (animType) {
case ANIM_TYPE_ALPHA:
animRes = R.anim.alpha;
break;
case ANIM_TYPE_SCALE:
animRes = R.anim.scale;
break;
case ANIM_TYPE_TRANSLATE:
animRes = R.anim.translate;
break;
case ANIM_TYPE_ROTATE:
animRes = R.anim.rotate;
break;
case ANIM_TYPE_SET:
animRes = R.anim.set;
break;
default:
animRes = ANIM_TYPE_ALPHA;
break;
}
Animation animation = AnimationUtils.loadAnimation(this, animRes);
if (repeatMode != 0) {
animation.setRepeatCount(1);
animation.setRepeatMode(repeatMode);
}
// 动画监听
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
mIvAnim.startAnimation(animation);
}
}
2逐帧(Frame)动画
(根元素:<animation-list…/>
,在res/drawable目录)
逐帧动画就是把动画过程的每张静态图片收集起来后由Android依次显示出来。
<animation-list xmlns:android=”http://schemas.android.com/apk/res/android”
android:oneshot=[“true” | “false”]>
<item android:drawable=”@[package:]drawable/drawable_resource_name”
android:duration=”integer/>
</animation-list>
说明:
- android:oneshot:控制该动画是否循环播放,true不会循环,false循环。每个<item…/>子元素增加一帧。
程序获取AnimationDrawable对象之后,习惯上把AnimationDrawable设置成ImageView背景显示动画。
imageView.setImageResource(动画资源id);
AnimationDrawable drawable = (AnimationDrawable)imageView.getDrawable();
- drawable目录下:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/ic_launcher"
android:duration="1000"/>
<item android:drawable="@drawable/ic_launcher_round"
android:duration="1000"/>
</animation-list>
public class FrameAnimActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_frame_anim);
final ImageView ivAnim = findViewById(R.id.iv_anim);
findViewById(R.id.btn_start_anim).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ivAnim.setImageResource(R.drawable.frame_anim);
AnimationDrawable drawable = (AnimationDrawable) ivAnim.getDrawable();
if (drawable != null) {
Log.i("tag", "drawable exist");
}
}
});
}
}