Android动画基础

Android动画基础

课程目标:

1. 了解定义逐帧动画的方法

2. 掌握定义视图动画的方法

3. 掌握定义属性动画的方法

 

学习内容:

1. 逐帧动画

2. 视图动画系统

3. 属性动画系统  *

 

一、 逐帧动画:

Android中我们可以通过AnimationDrawable 这个对象来定义逐帧动画。我们可以通过在xml文件中定义 <animation-list> 来共同完成逐帧动画。

原理: 它操作的对象是一张张图片,通过将一张张图片循环播放,然后形成动画。

实践:

1. 在drawable目录下创建一个xml文件:

<?xml version="1.0" encoding="utf-8"?>

<animation-list android:oneshot="true"

    xmlns:android="http://schemas.android.com/apk/res/android">

    <item

        android:drawable="@drawable/frame_1"

        android:duration="100" />



    <item

        android:drawable="@drawable/frame_2"

        android:duration="100" />



    <item

        android:drawable="@drawable/frame_3"

        android:duration="100" />

</animation-list>

注释: 每一个item就是一帧图片,duration 代表的是显示时间。上面这个xml文件就是一个AnimationDrawable对象。android:oneshot属性是让动画只播放一遍。

2.java代码

public class FrameAnimationActivity extends AppCompatActivity {



    private AnimationDrawable animationDrawable;



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_frame_animation);



        View view = findViewById(R.id.view);

        animationDrawable = (AnimationDrawable) view.getBackground();

        // 让动画只播放一遍就结束,默认是循环播放。

        animationDrawable.setOneShot(true);

    }



    public void onClick(View view) {

        switch (view.getId()) {

            case R.id.btnStart:

                // 开始播放

                animationDrawable.start();

                break;

            case R.id.btnStop:

                // 结束播放

                animationDrawable.stop();

                break;

        }

    }

}

3.xml布局文件:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:id="@+id/activity_frame_animation"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context="com.animation.frame.FrameAnimationActivity">



    <View

        android:id="@+id/view"

        android:background="@drawable/loading"

        android:layout_centerInParent="true"

        android:layout_width="300dp"

        android:layout_height="300dp" />



    <LinearLayout

        android:layout_alignParentBottom="true"

        android:orientation="horizontal"

        android:layout_width="match_parent"

        android:layout_height="wrap_content">



        <Button

            android:id="@+id/btnStart"

            android:text="Start"

            android:onClick="onClick"

            android:layout_width="0dp"

            android:layout_weight="1"

            android:layout_height="wrap_content" />



        <Button

            android:id="@+id/btnStop"

            android:text="Stop"

            android:onClick="onClick"

            android:layout_width="0dp"

            android:layout_weight="1"

            android:layout_height="wrap_content" />

    </LinearLayout>



</RelativeLayout>

以上就是逐帧动画的全部内容。

 

二、 视图动画系统

它操作的是Android中的视图对象。也就是说我们可以通过视图动画系统可以让视图对象(如:TextView、 Button、ImageView等)动起来。

视图动画系统相关的类定义在 android.view.animation 包中,这个包里有个Animation 抽象类,我们可以通过Animation 的实现类: AlphaAnimation、ScaleAnimation、TranslateAnimation、RotateAnimation、AnimationSet等通过补间动画(补间动画:简单理解就是对一个视图对象,给定一个起始点,一个终点然后在一定的时间完成相应的动画)完成视图动画。

 

1.AlphaAnimation(透明度动画)

我们有两种方式完成: 1. 通过xml文件  2. 通过java代码

如果通过xml文件,我们可以将根标签设为<alpha>,这样的一个xml文件就对应一个AlphaAnimation对象。

 

2.ScaleAnimation(缩放动画)

我们有两种方式完成: 1. 通过xml文件  2. 通过java代码

如果通过xml文件,我们可以将根标签设为<scale>,这样的一个xml文件就对应一个ScaleAnimation对象。对一个视图对象在x轴或者y轴进行缩放。

 

3.TranslateAnimation(平移动画)

我们有两种方式完成: 1. 通过xml文件  2. 通过java代码

如果通过xml文件,我们可以将根标签设为<translate>,这样的一个xml文件就对应一个TranslateAnimation对象。对一个视图对象在x轴或者y轴进行平移。

 

4.RotateAnimation(平移动画)

我们有两种方式完成: 1. 通过xml文件  2. 通过java代码

如果通过xml文件,我们可以将根标签设为<rotate>,这样的一个xml文件就对应一个RotateAnimation对象。对一个视图对象在x轴或者y轴进行旋转。

 

5.AnimationSet(集合动画)

我们有两种方式完成: 1. 通过xml文件  2. 通过java代码

如果通过xml文件,我们可以将根标签设为<set>,这样的一个xml文件就对应一个AnimationSet对象。对视图同时执行上面的动画。

 

6.Interpolator(视图动画之插值器)

通过插值器可以定义我们视图动画的变化率,一般可以通过贝塞尔曲线来完成。

 

实践:

1.在/res目录下新建一个目录/res/anim,然后再创建一个/res/anim/alpha.xml文件(透明度动画):

​
<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android">



    <alpha

        android:duration="1000"

        <!-- 浮点数,起始透明度,1.0代表不透明, 0.0代表完全透明 -->

        android:fromAlpha="1.0"

        <!-- 终点透明度 -->

        android:toAlpha="0.1" />



</set>

/res/anim/scale.xml文件(缩放动画)

​
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000">

    <scale
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        <!-- x轴扩大2倍 -->
        android:toXScale="2.0"
               <!--  y轴不变 -->
        android:toYScale="1.0" />

    <!-- pivotX和pivotY是缩放的基准点,默认是视图的原点,也就是左上角, %就是相对于视图本身的比例, %p是相对于视图父控件的长度比例。  android:fillAfter属性是动画保持停止后状态,默认false。 -->

</set>

/res/anim/tranlate.xml文件(平移动画)

​
<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android"

    android:fillAfter="true">

    <translate

        android:duration="@android:integer/config_shortAnimTime"

        android:fromXDelta="0"

        android:fromYDelta="0"

        android:toXDelta="80%p"

        android:toYDelta="0" />

</set>

/res/anim/rotate.xml文件(旋转动画)

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android"

    android:fillAfter="true">



    <rotate

        android:fromDegrees="0"

        android:duration="300"

        android:toDegrees="360"

        android:pivotX="50%"

        android:pivotY="50%"

        android:repeatCount="infinite"

        />

        <!-- android:repeatCount重复播放次数,infinite表示无限循环; android:repeatMode: restart 表示从起始位置重复播放, reverse表示重复播放时原路返回播放。-->



</set>

/res/anim/set.xml文件(集合动画)

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android">



    <rotate

        android:duration="1000"

        android:fromDegrees="0"

        android:toDegrees="720"

        android:pivotX="50%"

        android:pivotY="50%"

        />



    <translate

        android:duration="1000"

        android:startOffset="1000"

        android:fromXDelta="0"

        android:toXDelta="500"

        android:fromYDelta="0"

        android:toYDelta="0"

        />

    <!-- android:startOffset 等待多长时间开始这个动画。 -->    

</set>

 

2.java代码:

public class ViewAnimationActivity extends AppCompatActivity {



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_view_animation);

    }



    @Override

    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.renew, menu);

        return super.onCreateOptionsMenu(menu);

    }



    @Override

    public boolean onOptionsItemSelected(MenuItem item) {

        switch (item.getItemId()) {

            case R.id.renew:

                // 重建activity

                recreate();

                break;

        }

        return super.onOptionsItemSelected(item);

    }



    public void onClick(View view) {

        switch (view.getId()) {

            case R.id.viewAlphaAnimation:

                // 视图动画之透明度动画

                Animation alphaAnimation = AnimationUtils.loadAnimation(this, R.anim.alpha);

                view.startAnimation(alphaAnimation);

                break;

            case R.id.viewScaleAnimation:

                 //  视图动画之缩放动画

                Animation scaleAnimation = AnimationUtils.loadAnimation(this, R.anim.scale);

                view.startAnimation(scaleAnimation);

                break;

            case R.id.viewTranslateAnimation:

                 //  视图动画之平移动画

                Animation translateAnimation = AnimationUtils.loadAnimation(this, R.anim.translate);

                view.startAnimation(translateAnimation);

                break;

            case R.id.viewRotateAnimation:

                //  视图动画之旋转动画

                Animation rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.rotate);

                view.startAnimation(rotateAnimation);

                break;

            case R.id.viewSetAnimation:

                // 集合动画

                Animation setAnimation = AnimationUtils.loadAnimation(this, R.anim.set);

                view.startAnimation(setAnimation);

                break;

            case R.id.viewLinear:

            case R.id.viewAccelerate:

                // 视图动画之插值器

                View viewLinear = findViewById(R.id.viewLinear);

                View viewAccelerate = findViewById(R.id.viewAccelerate);



                Animation animationLinear = AnimationUtils.loadAnimation(this, R.anim.translate);

                Animation animationAccelerate = AnimationUtils.loadAnimation(this, R.anim.translate);

                // 线性插值器

                animationLinear.setInterpolator(new LinearInterpolator());

                // 加速插值器

                animationAccelerate.setInterpolator(new AccelerateInterpolator());



                viewLinear.startAnimation(animationLinear);

                viewAccelerate.startAnimation(animationAccelerate);



                break;

        }

    }

}

3.布局xml文件:

<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"

    xmlns:tools="http://schemas.android.com/tools"

    android:id="@+id/activity_view_animation"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:paddingBottom="@dimen/activity_vertical_margin"

    android:paddingLeft="@dimen/activity_horizontal_margin"

    android:paddingRight="@dimen/activity_horizontal_margin"

    android:paddingTop="@dimen/activity_vertical_margin"

    tools:context="com.animation.view.ViewAnimationActivity">



    <LinearLayout

        android:background="@drawable/edge"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="vertical">



        <View

            android:id="@+id/viewAccelerate"

            android:background="@color/colorPrimary"

            android:layout_margin="8dp"

            android:layout_width="50dp"

            android:onClick="onClick"

            android:layout_height="50dp"/>



        <View

            android:id="@+id/viewLinear"

            android:alpha="0.5"

            android:background="@color/colorPrimary"

            android:layout_margin="8dp"

            android:layout_width="50dp"

            android:onClick="onClick"

            android:layout_height="50dp"/>



        <TextView

            android:id="@+id/viewAlphaAnimation"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="onClick"

            android:text="Alpha"

            style="@style/AnimationTextView" />



        <TextView

            android:id="@+id/viewScaleAnimation"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_gravity="center_horizontal"

            android:onClick="onClick"

            android:text="Scale"

            style="@style/AnimationTextView" />



        <TextView

            android:id="@+id/viewTranslateAnimation"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="onClick"

            android:text="Translate"

            style="@style/AnimationTextView" />



        <TextView

            android:id="@+id/viewRotateAnimation"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="onClick"

            android:text="Rotate"

            android:layout_gravity="center_horizontal"

            style="@style/AnimationTextView" />



        <TextView

            android:id="@+id/viewSetAnimation"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:onClick="onClick"

            android:text="Set"

            style="@style/AnimationTextView" />



        <View

            android:layout_width="match_parent"

            android:layout_height="200dp" />



    </LinearLayout>

</ScrollView>

/res/values/style.xml文件:

<resources>

    <!-- Base application theme. -->

    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">

        <!-- Customize your theme here. -->

        <item name="colorPrimary">@color/colorPrimary</item>

        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>

        <item name="colorAccent">@color/colorAccent</item>

    </style>



    <style name="AnimationTextView">

        <item name="android:background">@color/colorPrimary</item>

        <item name="android:padding">16dp</item>

        <item name="android:layout_margin">8dp</item>

        <item name="android:textAppearance">@style/TextAppearance.AppCompat.Large</item>

        <item name="android:textColor">@android:color/white</item>

    </style>



</resources>

/res/drawable/edge.xml

<?xml version="1.0" encoding="utf-8"?>

<shape xmlns:android="http://schemas.android.com/apk/res/android">



    <solid android:color="@android:color/transparent" />



    <stroke

        android:width="1px"

        android:color="@android:color/black" />



</shape>

三、属性动画

原理: 在相应的时间内通过不断的改变对象属性值的方式形成动画。这个属性的值有一个起始值和一个结束值,然后Animator对象就可以驱动完成这个过渡的过程,形成动画效果,所以Animator对象就是属性动画的驱动器。

属性动画相关的类都在android.animation包中,这个包中的抽象类Animator 就是属性动画相关的类,ValueAnimator就是抽象类Animator的实现类。

 

视图动画 VS 属性动画:

1. 操作对象

视图动画只能操作视图对象,但是属性动画可以操作任意对象。

2. 属性

视图动画呈现变化的只是效果,并不能改变视图对象实际的属性;但是属性动画不仅可以呈现

出动画效果还能改变对象真正的属性。视图动画所能完成的属性动画也都能完成,但是属性动

画能完成的,视图动画很多却不能做到,所以综合来说属性动画更为强大。

 

属性动画可以定义的动画属性:

1. 动画的时长

2. 时间插值器(动画完成时间的变化率)

3. 重复次数以及重复模式

4. 动画集(就是几种动画效果的集合)

5. 延迟(延迟多久开始执行动画)

 

ValueAnimator能够改变属性的值,但是我们并不能指定改变哪个对象的属性值。ObjectAnimator就能够指定我们能够改变哪个对象的属性值,它是valueAnimator的子类。和视图动画一样,我们可以在xml文件中指定ObjectValue对象,也可以通过java代码来指定。如果在xml文件中指定,根标签为<objectAnimator>,每个objectAnimator标签对应一个ObjectAnimator对象。在属性动画中我们通过AnimatorInflater工具类来从资源文件中加载属性动画。

 

虽然属性动画可以让任何对象都可以产生动画,但是大多数情况下我们都是让View视图产生动画效果,为此,Android中为我们实现View视图动画,专门提供了ViewPropertyAnimator类。使用方法:

a. 通过view.animate()方法获取一个ViewPropertyAnimator 对象。

b. 再调用要改变的相应的属性值,然后调用start() 方法即可产生动画效果。

eg: view.animate().translationX(500f).setDuration(1000).start();

 

1.在xml中定义改变透明度的objectAnimator对象:

在res/目录下新建一个animator目录: res/animator/alpha.xml

<?xml version="1.0" encoding="utf-8"?>

<set xmlns:android="http://schemas.android.com/apk/res/android">



    <objectAnimator

        android:propertyName="alpha"   <!-- 改变的属性值,一定要确保目标对象中有这个属性值的set方法,否则无效 -->

        android:duration="1000"

        android:valueType="floatType"

        android:valueFrom="1.0"

        android:valueTo="0.1"

        />



</set>

实践;

1.java代码:

public class PropertyActivity extends AppCompatActivity {



    private static final String TAG = "PropertyActivity";



    @Override

    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_property);

    }



    public void onClick(View view) {

        switch (view.getId()) {

//            case R.id.btnValueAnimator:

//                ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 1.0f);

                  // 属性动画的时间插值器

//                valueAnimator.setInterpolator(new LinearInterpolator());

//                valueAnimator.setDuration(100);

                  // 属性动画的监听器(监听属性动画完成的过程)

//                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

//                    @Override

//                    public void onAnimationUpdate(ValueAnimator animation) {

                          // 属性动画中属性值的完成度

//                        float animatedFraction = animation.getAnimatedFraction();

                          // 属性动画中属性值的具体值

//                        float animatedValue = (float) animation.getAnimatedValue();

//                        Log.d(TAG, "onAnimationUpdate: " + String.format("%.3f  %.3f", animatedFraction, animatedValue));

//                    }

//                });

//                valueAnimator.start();

//                break;

            case R.id.viewAlphaAnimation:

                // 通过xml文件定义ObjectAnimator对象,改变这个对象的透明度

                Animator alphaAnimator = AnimatorInflater.loadAnimator(this, R.animator.alpha);

                // 设置目标对象

                alphaAnimator.setTarget(view);

                alphaAnimator.start();

                break;

            case R.id.viewScaleAnimation:

                // 通过java代码使目标对象view产生缩放动画

                ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 3.0f).start();

                break;

            case R.id.viewTranslateAnimation:

                // 通过ViewPropertyAnimator 对象产生视图对象的平移属性的动画效果

                view.animate().translationX(500f).setDuration(1000).start();

                break;

            case R.id.viewRotateAnimation:

                             //  通过ViewPropertyAnimator 对象产生视图对象的翻转属性的动画效果

                view.animate().rotation(720).start();

                break;

            case R.id.viewSetAnimation:

                                 // 实现属性动画集合(两种方法)

                                 //  方法一:  通过AnimatorSet 对象实现属性动画集合

//                Animator rotateAnimator = ObjectAnimator.ofFloat(view, "rotation", 0, 720);

//                rotateAnimator.setDuration(1000);

//

//                Animator moveAnimator = ObjectAnimator.ofFloat(view, "x", 0, 500);

//                moveAnimator.setDuration(1000);

//

//                AnimatorSet set = new AnimatorSet();

                  // 同时实现翻转和平移动画    

//                set.playTogether(rotateAnimator, moveAnimator);

                  // 顺序完成属性动画,先翻转再平移

//                set.playSequentially(rotateAnimator, moveAnimator);

//                set.start();



                // 方法二: 通过 ViewPropertyAnimator 对象实现属性动画集合效果

                view.animate().rotation(720).setDuration(1000).start();

                view.animate().translationX(500).setDuration(1000).setStartDelay(1000).start();



                break;

        }

    }



}

 

 

 

 

 

 

 

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值