Android 动画学习

目录

一、动画实现方式

 二、补间动画

2.1、作用对象

2.2、原理

2.3、类型分类

2.4、具体使用

2.4.1、平移动画

2.4.2、旋转动画

2.4.3、缩放动画

2.4.4、透明度动画

2.4.5、组合动画

三、逐帧动画

3.1、概述

3.2、使用步骤

3.3、代码示例

四、属性动画(Property Animation)

4.1、作用对象

4.2、工作原理

4.3、具体使用

4.3.1、ValueAnimation类

4.3.2、ObjectAnimator

五、动画监听

六、动画的总结和对比


一、动画实现方式

 二、补间动画

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) {  
    // 如想只想监听动画开始时刻,就只需要单独重写该方法就可以
    }  
});

六、动画的总结和对比

属性动画(改变)和视图动画(未改变)的区别在于:是否改变对象本身的属性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值