目录
一、动画实现方式
二、补间动画
2.1、作用对象
视图控件,不可作用于View组件的属性(如颜色,背景)。
2.2、原理
通过确定开始的视图样式 & 结束的视图样式、中间动画变化过程由系统补全来确定一个动画。
结束的视图样式:平移、缩放、旋转 & 透明度样式 ,即补间动画的动画效果就是:平移、缩放、旋转 & 透明度动画。
2.3、类型分类
根据不同的动画效果,补间动画分为以下四种:
2.4、具体使用
2.4.1、平移动画
2.4.1.1、XML文件使用
步骤一:在res下新建anim文件夹并创建动画效果xml文件;
步骤二:书写xml文件内容;
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
//以下参数是4种动画效果的公共属性,即都有的属性
android:duration="3000" //动画持续时间(ms),必须设置,动画才有效果
android:startOffset="1000" //动画延时开始时间
android:fillBefore="true" //动画播放完后,视图是否会停留在动画开始的状态,默认为true
android:fillAfter="true" //动画播放完后,视图是否会停留在动画结束的状态,优先于fillBefore值,默认为false
android:fillEnabled="true"//是否应用fillBefore值,对fillAfter值无影响,默认为true
android:repeatMode="restart"// 选择重复播放动画模式,restart代表正序重放,reverse代表倒序回放,默认为restart
android:repeatCount ="0" // 重放次数(所以动画的播放次数=重放次数+1),为infinite时无限重复
android:interpolator = @[package:]anim/interpolator_resource // 插值器,即影响动画的播放速度
>
<translate
android:fromXDelta="0" //水平方向上X移动的起始值
android:toXDelta="300" //水平方向上X移动的结束值
android:fromYDelta="0" //水平方向上Y移动的起始值
android:toYDelta="0" //水平方向上Y移动的结束值
/>
</set>
步骤三:在java代码中使用;
//创建动画并传入设置的动画效果文件
Animation translateAnimation = AnimationUtils.loadAnimation(this, R.anim.view_translate);
//播放动画
text.startAnimation(translateAnimation);
使用方式步骤:
1、编写需要使用动画的xml文件;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:src="@drawable/warter"
android:layout_width="200dp"
android:layout_height="200dp"/>
</LinearLayout>
2、编写动画xml文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:startOffset="1000"
android:fillBefore="true"
android:fillAfter="false"
android:fillEnabled="true"
android:repeatMode="restart"
android:repeatCount ="0">
<translate
android:fromXDelta="0"
android:toXDelta="500"
android:fromYDelta="0"
android:toYDelta="800" />
</set>
3、使用动画加载
public class TranslateActivity extends AppCompatActivity {
private ImageView mImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_translate);
mImageView = findViewById(R.id.image);
//第一种方式
Animation animation = AnimationUtils.loadAnimation(this, R.anim.translate_animation);
mImageView.startAnimation(animation);
}
}
2.4.1.2、不使用xml文件
1、编写需要使用动画的xml文件;
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/image"
android:src="@drawable/warter"
android:layout_width="200dp"
android:layout_height="200dp"/>
</LinearLayout>
2、直接使用TranslateAnimation类
public class TranslateActivity extends AppCompatActivity {
private ImageView mImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_translate);
mImageView = findViewById(R.id.image);
//第二种方式
// 创建平移动画的对象,平移动画对应的Animation子类为TranslateAnimation
TranslateAnimation translateAnimation = new TranslateAnimation(0, 400, 0, 500);
//属性设置:方法名是在其属性前加“set”,如设置时长setDuration()
translateAnimation.setDuration(3000);
//设置重复次数,-1表示无限次循环
translateAnimation.setRepeatCount(-1);
mImageView.startAnimation(translateAnimation);
}
}
TranslateActivity常用构造方法有两种:
1、public TranslateAnimation(float fromXDelta, float toXDelta,float fromYDelta, float toYDelta)
该种方式表示动画开始位置和结束位置以当前View X/Y为具体值;
2、public TranslateAnimation (int fromXType, float fromXValue,int toXType, float toXValue,
int fromYType, float fromYValue,int toYType, float toYValue)
该种方式表示动画开始位置和结束位置以当前View X/Y为具体值;由Type值控制;type值有三种:ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT。
ABSOLUTE时:值为具体数值
RELATIVE_TO_SELF:表示以View左上角为原点沿坐标轴正方向偏移View宽/高度的pivotXValue和pivotYValue值;
RELATIVE_TO_PARENT:表示以View左上角为原点沿坐标轴正方向偏移父(parent)控件宽/高度的pivotXValue和pivotYValue值;
2.4.2、旋转动画
2.4.2.1、使用XML文件
1、动画文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000"
android:fillAfter="true"
android:repeatMode="reverse">
<rotate android:fromDegrees="0"
android:toDegrees="180"
android:pivotX="50%"
android:pivotY="50%"
/>
</set>
2、属性解释:
fromDegrees、toDegrees :起始、终止角度
pivotX、pivotY:旋转中心点
from=负数->to=正数:表示顺时针旋转
from=负数->to=负数:表示逆时针旋转
from=正数->to=正数:表示顺时针旋转
from=正数->to=负数:表示逆时针旋转
pivotX和pivotY 有三种类型的值:
100:表示以当前View左上角为原点沿坐标轴正方向偏移100px
50%:表示以View左上角为原点沿坐标轴正方向偏移View宽/高度的50%;
50%p:表示以View左上角为原点沿坐标轴正方向偏移父(parent)控件宽/高度的50%。
3、使用动画
ImageView view = findViewById(R.id.img);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate_animation);
view.startAnimation(animation);
2.4.2.2、不使用XML文件
RotateAnimation ra = new RotateAnimation(0,180,
Animation.RELATIVE_TO_SELF,0.5F,
Animation.RELATIVE_TO_SELF,0.5F);
ra.setDuration(2000);
ra.setFillAfter(true);
ra.setRepeatCount(-1);
ra.setRepeatMode(REVERSE);
view.startAnimation(ra);
2.4.3、缩放动画
2.4.3.1、使用xml文件
1、动画文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000">
<scale
android:fromXScale="0.3"
android:fromYScale="0.3"
android:toXScale="1.0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
2、动画文件属性说明
android:duration 补间时长
android:fromXScale/android:toXScale 起始和结束X轴缩放度比例
android:fromYScale/android:toYScale 起始和结束Y轴缩放度比例
android:pivotX="50%"/android:pivotY="50%" 设置缩放点的位置
值=0.0 :表示收缩到没有
值<1.0 :表示收缩
值=1.0 :表示无伸缩
值>1.0 :表示放大
pivotX和pivotY 有三种类型的值:
100:表示以当前View左上角为原点沿坐标轴正方向偏移100px
50%:表示以View左上角为原点沿坐标轴正方向偏移View宽/高度的50%;
50%p:表示以View左上角为原点沿坐标轴正方向偏移父(parent)控件宽/高度的50%。
3、使用动画
ImageView view = findViewById(R.id.img);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale_animation);
view.startAnimation(animation);
2.4.3.1、不使用xml文件
ImageView view = findViewById(R.id.img);
ScaleAnimation sa = new ScaleAnimation(0.2f, 1f, 0.2f, 1f,
Animation.RELATIVE_TO_SELF,0.5f,
Animation.RELATIVE_TO_SELF,0.5f);
sa.setDuration(1000);
sa.setFillAfter(true);
view.startAnimation(sa);
ScaleAnimation构造函数有三种:
public ScaleAnimation(float fromX, float toX, float fromY, float toY){}
该种方式表示以当前view的左上角为缩放中心进行变换;
public ScaleAnimation(float fromX, float toX, float fromY, float toY,float pivotX, float pivotY){}
该种方式表示以当前view的左上角偏移pivotX和pivotY为缩放中心进行变换;值为具体像素值;
public ScaleAnimation(float fromX, float toX, float fromY, float toY,int pivotXType,
float pivotXValue,int pivotYType, float pivotYValue){}
pivotXType值有三种:ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT。
ABSOLUTE时:和第二种构造函数一样
RELATIVE_TO_SELF:表示以View左上角为原点沿坐标轴正方向偏移View宽/高度的pivotXValue和pivotYValue值;
RELATIVE_TO_PARENT:表示以View左上角为原点沿坐标轴正方向偏移父(parent)控件宽/高度的pivotXValue和pivotYValue值;
2.4.4、透明度动画
2.4.4.1、使用XML文件
1、动画文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="2000">
<alpha android:fromAlpha="1.0"
android:toAlpha="0.1"/>
</set>
2、动画文件属性说明:
android:duration 补间时长
android:fromAlpha 起始透明度
android:toAlpha 终止时透明度
3、使用动画文件
TextView textView = findViewById(R.id.viewAlphaAnimation);
//调用AnimationUtils中的loadAnimation(),把定义好的alpha.xml动画资源文件加载进来,
// 一参为context,二参为资源文件id;
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha_animation);
textView.startAnimation(animation);
2.4.4.2、不使用XML文件
AlphaAnimation aa = new AlphaAnimation(1,0);
aa.setDuration(2000);
aa.setRepeatCount(-1);
textView.startAnimation(aa);
2.4.5、组合动画
1、动画文件
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:duration="2000"
android:repeatCount="infinite"/>
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="500"
android:toYDelta="0"
android:duration="2000"
android:startOffset="4000"
android:repeatCount="infinite"/>
</set>
2、使用
View view = findViewById(R.id.view);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.rotate_translate);
view.startAnimation(animation);
组合动画这里介绍的比较简单,有详细的介绍,请看这篇文章:Android动画之AnimatorSet联合动画用法 - 简书
三、逐帧动画
3.1、概述
逐帧动画也称图片动画,通过在一个固定区域,逐张地呈现一系列事先加载好的图片而产生动画效果;
3.2、使用步骤
1、导入需要形成帧动画的图片资源;
2、在drawable文件夹下,新建一个animation_list文件,每一个item放入一张图片,指定加载时间;
3、在需要使用的xml文件中引入一个View组件,把这个组件的background设置为该动画布局;
4、获取这个组件的background,强转为AnimationDrawable,调用start、stop方法开始或关闭动画;
3.3、代码示例
3.3.1、动画xml文件:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/cicle1"
android:duration="200"/>
<item android:drawable="@drawable/cicle2"
android:duration="200"/>
<item android:drawable="@drawable/cicle3"
android:duration="200"/>
<item android:drawable="@drawable/cicle4"
android:duration="200"/>
<item android:drawable="@drawable/cicle5"
android:duration="200"/>
</animation-list>
3.3.2、使用
<View
android:id="@+id/view"
android:background="@drawable/cicle_change"
android:layout_centerInParent="true"
android:layout_width="800dp"
android:layout_height="800dp"/>
//view.getBackground()返回的是一个Drawable对象,在这里已经明确背景是AnimationDrawable,
// 所以可以做一个强制转换(窄化、向下转型)
mAnimationDrawable = (AnimationDrawable) mView.getBackground();
mAnimationDrawable.start();
mAnimationDrawable.stop();
3.3.3、设置只运行一次
java代码中设置:animationDrawable.setOneShot(true);
xml文件中设置:<animation-list>添加android:oneshot="true"属性
3.3.4、java代码实现
mAnimationDrawable = new AnimationDrawable();
int [] resID = {R.drawable.cicle1, R.drawable.cicle2, R.drawable.cicle3,
R.drawable.cicle4, R.drawable.cicle5};
for (int id : resID) {
mAnimationDrawable.addFrame(getResources().getDrawable(id, null), 100);
}
mView.setBackground(mAnimationDrawable);
mAnimationDrawable.start();
mAnimationDrawable.stop();
四、属性动画(Property Animation)
4.1、作用对象
任意 Java
对象,即不再局限于视图View对象。
4.2、工作原理
在一定时间间隔内,通过不断对值进行改变、不断将该值赋给对象的属性(任意对象的任意属性),从而实现该对象在该属性上的动画效果。
4.3、具体使用
4.3.1、ValueAnimation类
- 定义:属性动画机制中 最核心的一个类
- 实现动画的原理:通过不断控制值的变化,再不断手动赋给对象的属性,从而实现动画效果。
4.3.2、ObjectAnimator
实现原理:直接对对象的属性值进行改变操作,从而实现动画效果。继承自ValueAnimator
类,即底层的动画实现机制是基于ValueAnimator
类。
本质原理: 通过不断控制值的变化,再不断自动赋给对象的属性,从而实现动画效果。
xml实现:
步骤1:在路径res/animator 的文件夹里创建动画效果.xml文件,
此处设置为res/animator/set_animation.xml
步骤2:设置动画参数 set_animation.xml
// ObjectAnimator 采用<animator> 标签
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
android:valueFrom="1" // 初始值
android:valueTo="0" // 结束值
android:valueType="floatType" // 变化值类型 :floatType & intType
android:propertyName="alpha" // 对象变化的属性名称
/>
步骤3:启动动画
Animator animator = AnimatorInflater.loadAnimator(context, R.animator.view_animation);
// 载入XML动画
animator.setTarget(view);
// 设置动画对象
animator.start();
// 启动动画
java实现:
ObjectAnimator animator = ObjectAnimator.ofFloat(Object object, String property, float ....values);
// ofFloat()作用有两个
// 1. 创建动画实例
// 2. 参数设置:参数说明如下
// Object object:需要操作的对象
// String property:需要操作的对象的属性
// float ....values:动画初始值 & 结束值(不固定长度)
// 若是两个参数a,b,则动画效果则是从属性的a值到b值
// 若是三个参数a,b,c,则则动画效果则是从属性的a值到b值再到c值
// 以此类推
// 至于如何从初始值 过渡到 结束值,同样是由估值器决定
// 此处ObjectAnimator.ofFloat()是有系统内置的浮点型估值器FloatEvaluator,同ValueAnimator讲解
anim.setDuration(500); // 设置动画运行的时长
anim.setStartDelay(500); // 设置动画延迟播放时间
anim.setRepeatCount(0);
anim.setRepeatMode(ValueAnimator.RESTART);
animator.start();
// 启动动画
使用实例:改变透明度
mButton = (Button) findViewById(R.id.Button);
// 创建动画作用对象:此处以Button为例
ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, "alpha", 1f, 0f, 1f);
// 表示的是:
// 动画作用对象是mButton
// 动画作用的对象的属性是透明度alpha
// 动画效果是:常规 - 全透明 - 常规
animator.setDuration(5000);
animator.start();
第二个参数还能传入什么属性值:任意值。第二个参数传入值的作用是:让ObjectAnimator类根据传入的属性名 去寻找 该对象对应属性名的 set() & get()方法,从而进行对象属性值的赋值。自动赋值的逻辑:
1.初始化时,如果属性的初始值没有提供,则调用属性的
get()
进行取值;2.当 值 变化时,用对象该属性的
set()
方法,从而从而将新的属性值设置给对象属性。
五、动画监听
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) {
//动画结束时执行
}
});
// 特别注意:每次监听必须4个方法都重写。
继承关系如下,所以AnimatorSet类、ValueAnimator、ObjectAnimator都可以使用addListener()监听器进行动画监听:
动画适配器AnimatorListenerAdapter
- 背景:有些时候我们并不需要监听动画的所有时刻
- 问题:但addListener(new AnimatorListener())监听器是必须重写4个时刻方法,这使得接口方法重写太累赘
- 解决方案:采用动画适配器(AnimatorListenerAdapter),解决实现接口繁琐 的问题
anim.addListener(new AnimatorListenerAdapter() {
// 向addListener()方法中传入适配器对象AnimatorListenerAdapter()
// 由于AnimatorListenerAdapter中已经实现好每个接口
// 所以这里不实现全部方法也不会报错
@Override
public void onAnimationStart(Animator animation) {
// 如想只想监听动画开始时刻,就只需要单独重写该方法就可以
}
});
六、动画的总结和对比
属性动画(改变)和视图动画(未改变)的区别在于:是否改变对象本身的属性。