动画分类
- 帧动画
- 补间动画 (View 动画)
- 属性动画
帧动画
简介
- 需要定义好动画的每一帧,然后系统的一帧一帧的播放。
- 缺点:因为逐帧动画的帧序列内容不一样,不但给制作增加了负担而且最终输出的文件量也很大。
- 优点: 逐帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容,而它类似与电影的播放模式,很适合于表演细腻的动画。
实现
使用java代码
- 帧动画播放器:AnimationDrawable ,常用方法如下图:
- AnimationDrawable.addFrame(Drawable,int) 方法中Drawable对象是对每一帧的图片,可以根据图片名称批量获取,如下:
for (int i = 0; i < 7; i++) {
animationDrawable.addFrame(getResources().getDrawable(getResources().getIdentifier ("ic_frame_" + i, "mipmap", getPackageName())), 200);
}
getResources().getIdentifier() 根据名称获取资源
使用xml
- 在 res/drawable 文件夹中定义动画 frame.xml,如下:
<?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_fingerprint_0" android:duration="100"/>
<item android:drawable="@drawable/ic_fingerprint_1" android:duration="100"/>
<item android:drawable="@drawable/ic_fingerprint_2" android:duration="100"/>
</animation-list>
- 然后在代码中获取到定义的动画文件,如下:
AnimationDrawable frame = (AnimationDrawable) ContextCompat.getDrawable(this, R.drawable.frame);
frame.start();
补间动画 (View 动画)
简介
- View动画定义了渐变Alpha、旋转Rotate、缩放Scale、平移Translate四种基本动画,并且通过这四种基本动画的组合使用,可以实现多种交互效果。
- View动画使用非常简单,不仅可以通过XML文件来定义动画,同样可以通过Java代码来实现动画过程。
实现
使用 java代码
- 旋转动画
/**
* 旋转动画
*/
private void rotateAnim() {
/**
参数分别是:
开始角度
结束角度
X轴起始点类型
X轴起始点值
Y轴起始点类型
Y轴起始点值
* 起始点类型 :RotateAnimation.RELATIVE_TO_SELF,RotateAnimation.RELATIVE_TO_PARENT,
* RotateAnimation.ABSOLUTE,若起始点类型为ABSOLUTE,则起始点的值是指定的值如:720,
* 其他的是0(0%)到1(100%)按百分比
*/
RotateAnimation animation = new RotateAnimation(0f, 360f, RotateAnimation.RELATIVE_TO_SELF,
0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
animation.setDuration(2000);
//动画监听
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) { }
@Override
public void onAnimationEnd(Animation animation) { }
@Override
public void onAnimationRepeat(Animation animation) { }
});
animation.setRepeatMode(Animation.REVERSE);//Animation.REVERSE 第二次反向;Animation.RESTART:一个方向
animation.setInterpolator(new AccelerateDecelerateInterpolator());//修改旋转过程中的速度
animation.setRepeatCount(200);//重复的次数
iv.setAnimation(animation);
//如果需要立即执行则可使用 iv.startAnimation(animation)
}
- 平移动画
private void translate() {
/**
* 参数分别是:
X轴起始点类型
X轴起始点值
X轴终点类型
X轴终点值
Y轴起始点类型
Y轴起始点值
Y轴终点类型
Y轴终点值
* 起始点类型 :RotateAnimation.RELATIVE_TO_SELF,RotateAnimation.RELATIVE_TO_PARENT,
* RotateAnimation.ABSOLUTE,若起始点类型为ABSOLUTE,则起始点的值是指定的值如,
* 其他的是0(0%)到1(100%)按百分比
*/
TranslateAnimation translateAnimation = new TranslateAnimation(
TranslateAnimation.RELATIVE_TO_SELF, 0f,
TranslateAnimation.RELATIVE_TO_SELF, 1f,
TranslateAnimation.RELATIVE_TO_SELF, 0f,
TranslateAnimation.RELATIVE_TO_SELF, 1f);
translateAnimation.setDuration(2000);
translateAnimation.setRepeatMode(Animation.REVERSE);
translateAnimation.setRepeatCount(200);
iv.setAnimation(translateAnimation);
}
- 缩放动画
private void scale() {
/**
* fromX:起始X坐标上的伸缩尺寸。
* toX:结束X坐标上的伸缩尺寸。
* fromY:起始Y坐标上的伸缩尺寸。
* toY:结束Y坐标上的伸缩尺寸。
* pivotXType:X轴的伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT。
* pivotXValue:X坐标的伸缩值。
* pivotYType:Y轴的伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT。
* pivotYValue:Y坐标的伸缩值。
*
* 伸缩模式 :RotateAnimation.RELATIVE_TO_SELF,RotateAnimation.RELATIVE_TO_PARENT,
* RotateAnimation.ABSOLUTE,若伸缩模式为ABSOLUTE,则起始点的值是指定的值如
* 其他的是0(0%)到1(100%)按百分比
*/
ScaleAnimation scaleAnimation = new ScaleAnimation(0f, 1, 0f, 1f,
ScaleAnimation.RELATIVE_TO_SELF, 0.5f,
ScaleAnimation.RELATIVE_TO_SELF, 0.5f);
scaleAnimation.setDuration(2000);
scaleAnimation.setRepeatMode(Animation.REVERSE);
scaleAnimation.setRepeatCount(200);
iv.setAnimation(scaleAnimation);
}
- 渐变动画
private void alpha() {
AlphaAnimation alphaAnimation = new AlphaAnimation(1f, 0f);
alphaAnimation.setDuration(2000);
alphaAnimation.setRepeatCount(200);
alphaAnimation.setRepeatMode(AlphaAnimation.REVERSE);
iv.setAnimation(alphaAnimation);
}
- 组合动画
private void set() {
/**
* shareInterpolator :使用同一个插值器
*/
animationSet = new AnimationSet(true);
animationSet.setDuration(2000);
animationSet.setFillAfter(true);// 为true动画结束时,View将保持动画结束时的状态
animationSet.setFillBefore(true);// 为true动画结束时,View将还原到开始开始时的状态
animationSet.setRepeatMode(Animation.REVERSE);
animationSet.setFillEnabled(true);//是否设置动画结束状态
animationSet.setInterpolator(new AccelerateDecelerateInterpolator());
animationSet.addAnimation(alphaAnimation);
animationSet.addAnimation(scaleAnimation);
animationSet.addAnimation(translateAnimation);
iv.setAnimation(animationSet);
}
使用 xml文件实现
- 在 res/anim文件夹下创建 view.xml,内容如下:
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillAfter="true"
android:repeatMode="restart"
android:shareInterpolator="true">
<alpha
android:fromAlpha="1"
android:toAlpha="0" />
<rotate
android:fromDegrees="0"
android:pivotY="50%"
android:toDegrees="360" />
<scale
android:fromXScale="1.0"
android:fromYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.5"
android:toYScale="0.5" />
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="100%"
android:toYDelta="0" />
</set>
java代码animation 类中的方法这里都有相应的属性
- 在代码中使用view.xml文件:
Animation animation=AnimationUtils.loadAnimation(this, R.anim.view);
iv.startAnimation(animation);
属性动画
简介
- 属性动画作用的对象是任意java对象,弥补了帧动画和view动画无法对非View的对象进行动画操作的缺陷。而且可自定义各种动画效果。
- 在一定时间间隔内,通过不断对值进行改变,并不断将该值赋给对象的属性,从而实现该对象在该属性上的动画效果
- 工作逻辑:
使用
ValueAnimator 类
-
ValueAnimator的主要方法有
- ValueAnimator.ofInt()
- ValueAnimator.ofFloat()
- ValueAnimator.ofObject()
- ValueAnimator.ofArgb()
- ValueAnimator.ofPropertyValuesHolder()
-
基本使用,以ofInt()为例
// 步骤1:设置动画属性的初始值 & 结束值
// ofInt()作用有两个
// 1. 创建动画实例
// 2. 将传入的多个Int参数进行平滑过渡:此处传入0和1,表示将值从0平滑过渡到1
// 如果传入了3个Int参数 a,b,c ,则是先从a平滑过渡到b,再从b平滑过渡到C,以此类推
// ValueAnimator.ofInt()内置了整型估值器,直接采用默认的.不需要设置,即默认设置了如///何从初始值 过渡到 结束值
ValueAnimator anim = ValueAnimator.ofInt(0, 3);
// 步骤2:设置动画的播放各种属性
anim.setDuration(500);
// 设置动画运行的时长
//设置动画的插值器
anim.setInterpolator(new AccelerateDecelerateInterpolator());
//设置动画的估值器
anim.setEvaluator(new IntEvaluator());
anim.setStartDelay(500);
// 设置动画延迟播放时间
anim.setRepeatCount(0);
// 设置动画重复播放次数 = 重放次数+1
// 动画播放次数 = infinite时,动画无限重复
anim.setRepeatMode(ValueAnimator.RESTART);
// 设置重复播放动画模式
// ValueAnimator.RESTART(默认):正序重放
// ValueAnimator.REVERSE:倒序回放
// 步骤3:将改变的值手动赋值给对象的属性值:通过动画的更新监听器
// 设置 值的更新监听器
// 即:值每次改变、变化一次,该方法就会被调用一次
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int currentValue = (Integer) animation.getAnimatedValue();
// 获得改变后的值
System.out.println(currentValue);
// 输出改变后的值
// 步骤4:将改变后的值赋给对象的属性值,
//如:view.setX( currentValue); 改变view的x坐标
view.setproperty(currentValue);
// 步骤5:刷新视图,即重新绘制,从而实现动画效果,View的某些属性改变会自动调用重绘的方法,这一步可以省略
view.requestLayout();
}
});
anim.start();
// 启动动画
}
-
在xml中的使用
- 在res/animator 文件夹中新建value.xml,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<animator xmlns:android="http://schemas.android.com/apk/res/android"
android:repeatMode="reverse"
android:repeatCount="100"
android:duration="2000"
android:valueFrom="0"
android:valueTo="500" />
- 在代码中使用value.xml
ValueAnimator valueAnimator= (ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.object);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
iv.setRadius((Float) animation.getAnimatedValue());
}
});
valueAnimator.start();
ObjectAnimator 类
-
主要的方法:
- ObjectAnimator.ofInt();
- ObjectAnimator.ofArgb();
- ObjectAnimator.ofMultiFloat();
- ObjectAnimator.ofObject();
- ObjectAnimator.ofMultiInt();
- ObjectAnimator.ofPropertyValuesHolder()
-
在java代码中的使用
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv, "rotationX", 0, 120, 240, 360);
objectAnimator.setDuration(2000);
objectAnimator.setRepeatCount(100);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.start();
-
在xml中的使用
- 在res/animator 文件夹中新建object.xml,内容如下:
<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:repeatMode="reverse"
android:repeatCount="100"
android:duration="2000"
android:valueFrom="0"
android:valueTo="500"
android:propertyName="scaleX"
android:valueType="floatType" />
- 在代码中使用object.xml
ObjectAnimator animator1 = (ObjectAnimator)AnimatorInflater.loadAnimator(this, R.animator.object);
animator1.setTarget(iv);
animator1.start();
组合动画 AnimatorSet
- 使用java代码
//使用ObjectAnimator
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(iv, "radius", 0, 120, 240, 360);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
//使用ValueAnimator
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 120, 240, 360);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (float) animation.getAnimatedValue();
iv.setRadius(value);
}
});
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.setDuration(2000);
animatorSet.playSequentially(objectAnimator,valueAnimator);//动画顺序播放
animatorSet.playTogether(objectAnimator,valueAnimator);//动画同时播放
/*
*还可以使用BUilder指定播放顺序
animatorSet.play(objectAnimator1)
.after(valueAnimator1)
.before(objectAnimator2)
.with(objectAnimator2);
*/
animatorSet.start();
- 使用xml,在res/animator文件夹下新建set.xml,内容如下
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially">
<animator
android:duration="2000"
android:propertyName="scaleX"
android:repeatCount="100"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="500"
android:valueType="floatType" />
<animator
android:duration="2000"
android:propertyName="scaleX"
android:repeatCount="100"
android:repeatMode="reverse"
android:valueFrom="0"
android:valueTo="500"
android:valueType="floatType" />
</set>
- 在代码中加载set.xml
animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this,R.animator.set);
animatorSet.setTarget(iv);
animatorSet.start();