补间动画就是指开发者指定动画的开始、动画的结束的"关键帧",而动画变化的"中间帧"由系统计算,并补齐。
补间动画有四种:
- 淡入淡出: alpha
- 位移:translate
- 缩放:scale
- 旋转: rotate
补间动画的实现方式有两种,类似于帧动画,
1、 XML 形式补间动画
补间动画一般也是通过 xml 来实现,对于 xml 形式补间动画的定义,也是需要在 res/anim/ 文件夹下定义动画资源,如:
alpha_anim.xml
(1)定义动画资源:res\anim\tween_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
>
<scale
android:duration="3000"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.0"
android:toYScale="1.0"/>
<alpha
android:duration="3000"
android:fromAlpha="1.0"
android:toAlpha="0.5" />
<rotate
android:fromDegrees="0"
android:toDegrees="720"
android:pivotX = "50%"
android:pivotY="50%"
android:duration = "3000"
/>
<translate
android:fromXDelta="0"
android:toXDelta="100"
android:fromYDelta="0"
android:toYDelta="100" />
</set>
(2)定义xml布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:padding="15dp"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:src="@mipmap/kaws4"/>
<Button
android:id="@+id/play2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="播放动画"
android:textSize="25sp"
android:textColor="#FFFFFF"
android:background="#000000"/>
</LinearLayout>
(3)Animation 控制图片播放动画
package com.example.androidtest;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
public class Animator3Activity extends AppCompatActivity {
// tween_image;
Button tween_start;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animator3);
final ImageView tween_image = findViewById(R.id.imv);
tween_start = findViewById(R.id.play2);
// 加载动画资源
final Animation anim = AnimationUtils.loadAnimation(this,R.anim.anim);
//设置动画结束后保留结束状态
anim.setFillAfter(true);
tween_start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
tween_image.startAnimation(anim);
}
});
}
}
效果如下:
2、Java 代码实现补间动画
Translate 位移
Animation translateAnimation = new TranslateAnimation(0,500,0,500);
// 创建平移动画的对象:平移动画对应的Animation子类为TranslateAnimation
// 参数分别是:
// 1. fromXDelta :视图在水平方向x 移动的起始值
// 2. toXDelta :视图在水平方向x 移动的结束值
// 3. fromYDelta :视图在竖直方向y 移动的起始值
// 4. toYDelta:视图在竖直方向y 移动的结束值
translateAnimation.setDuration(3000);
// 播放动画直接 startAnimation(translateAnimation)
//如:
mButton.startAnimation(translateAnimation);
- Scale: 缩放
Animation scaleAnimation= new ScaleAnimation(0,2,0,2,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
// 1. fromX :动画在水平方向X的结束缩放倍数
// 2. toX :动画在水平方向X的结束缩放倍数
// 3. fromY :动画开始前在竖直方向Y的起始缩放倍数
// 4. toY:动画在竖直方向Y的结束缩放倍数
// 5. pivotXType:缩放轴点的x坐标的模式
// 6. pivotXValue:缩放轴点x坐标的相对值
// 7. pivotYType:缩放轴点的y坐标的模式
// 8. pivotYValue:缩放轴点y坐标的相对值
// pivotXType = Animation.ABSOLUTE:缩放轴点的x坐标 = View左上角的原点 在x方向 加上 pivotXValue数值的点(y方向同理)
// pivotXType = Animation.RELATIVE_TO_SELF:缩放轴点的x坐标 = View左上角的原点 在x方向 加上 自身宽度乘上pivotXValue数值的值(y方向同理)
// pivotXType = Animation.RELATIVE_TO_PARENT:缩放轴点的x坐标 = View左上角的原点 在x方向 加上 父控件宽度乘上pivotXValue数值的值 (y方向同理)
scaleAnimation.setDuration(3000);
// 使用
mButton.startAnimation(scaleAnimation);
- Rotate: 旋转
Animation rotateAnimation = new RotateAnimation(0,270,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
// 1. fromDegrees :动画开始时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
// 2. toDegrees :动画结束时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
// 3. pivotXType:旋转轴点的x坐标的模式
// 4. pivotXValue:旋转轴点x坐标的相对值
// 5. pivotYType:旋转轴点的y坐标的模式
// 6. pivotYValue:旋转轴点y坐标的相对值
// pivotXType = Animation.ABSOLUTE:旋转轴点的x坐标 = View左上角的原点 在x方向 加上 pivotXValue数值的点(y方向同理)
// pivotXType = Animation.RELATIVE_TO_SELF:旋转轴点的x坐标 = View左上角的原点 在x方向 加上 自身宽度乘上pivotXValue数值的值(y方向同理)
// pivotXType = Animation.RELATIVE_TO_PARENT:旋转轴点的x坐标 = View左上角的原点 在x方向 加上 父控件宽度乘上pivotXValue数值的值 (y方向同理)
rotateAnimation.setDuration(3000);
mButton.startAnimation(rotateAnimation);
- Alpha 淡入淡出,渐变
Animation alphaAnimation = new AlphaAnimation(1,0);
// 1. fromAlpha:动画开始时视图的透明度(取值范围: -1 ~ 1)
// 2. toAlpha:动画结束时视图的透明度(取值范围: -1 ~ 1)
alphaAnimation.setDuration(3000);
mButton.startAnimation(alphaAnimation);
- 动画组合
// 组合动画设置
AnimationSet setAnimation = new AnimationSet(true);
// 特别说明以下情况
// 因为在下面的旋转动画设置了无限循环(RepeatCount = INFINITE)
// 所以动画不会结束,而是无限循环
// 所以组合动画的下面两行设置是无效的
setAnimation.setRepeatMode(Animation.RESTART);
setAnimation.setRepeatCount(1);// 设置了循环一次,但无效
// 旋转动画
Animation rotate = new RotateAnimation(0,360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
rotate.setDuration(1000);
rotate.setRepeatMode(Animation.RESTART);
rotate.setRepeatCount(Animation.INFINITE);
// 平移动画
Animation translate = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_PARENT,-0.5f,
TranslateAnimation.RELATIVE_TO_PARENT,0.5f,
TranslateAnimation.RELATIVE_TO_SELF,0
,TranslateAnimation.RELATIVE_TO_SELF,0);
translate.setDuration(10000);
// 透明度动画
Animation alpha = new AlphaAnimation(1,0);
alpha.setDuration(3000);
alpha.setStartOffset(7000);
// 缩放动画
Animation scale1 = new ScaleAnimation(1,0.5f,1,0.5f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
scale1.setDuration(1000);
scale1.setStartOffset(4000);
// 将创建的子动画添加到组合动画里
setAnimation.addAnimation(alpha);
setAnimation.addAnimation(rotate);
setAnimation.addAnimation(translate);
setAnimation.addAnimation(scale1);
// 使用
mButton.startAnimation(setAnimation);
动画监听
为了实现一些需求,如动画结束后开始另一个动画或者页面跳转,这时候就需要监听动画。
Animation.addListener(new AnimatorListener() {
@Override
public void onAnimationStart(Animation animation) {
//动画开始时执行
}
@Override
public void onAnimationRepeat(Animation animation) {
//动画重复时执行
}
@Override
public void onAnimationCancel()(Animation animation) {
//动画取消时执行
}
@Override
public void onAnimationEnd(Animation animation) {
//动画结束时执行
}
});
package com.example.androidtest;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.example.androidtest.R;
public class AnimatorActivity extends AppCompatActivity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_animator);
tv=findViewById(R.id.tv);
//tv.animate().translationYBy(500).setDuration(2000).start();//沿Y轴在2s内平移500个单位
//tv.animate().alpha(0).setDuration(2000).start();//2秒钟的渐变,从有到无
// ValueAnimator valueAnimator=ValueAnimator.ofInt(0,100);
// valueAnimator.setDuration(2000);
// valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
// @Override
// public void onAnimationUpdate(ValueAnimator valueAnimator) {
// //valueAnimator实际的值
// Log.d("aaaaa",valueAnimator.getAnimatedValue()+"");
// //动画的进度0-1
// Log.d("aaaaaaa",valueAnimator.getAnimatedFraction()+"");
// }
// });
// valueAnimator.start();
ObjectAnimator objectAnimator=ObjectAnimator.ofFloat(tv,"translationY",0,500,200,800);
//将tv从0移动到500再移动200
objectAnimator.setDuration(5000);
objectAnimator.start();
}
}