Android中動畫的詳細講解及其使用

概述:

在Android動畫中,總共有兩種類型的動畫View Animation(視圖動畫)和Property Animator(屬性動畫);
其中 :
a.View Animation包括Tween Animation(補間動畫)和Frame Animation(逐幀動畫);
b.Property Animator包括ValueAnimator和ObjectAnimation;
首先,直觀上,他們有如下三點不同
1、引入時間不同:View Animation是API Level 1就引入的。Property Animation是API Level 11引入的,即Android 3.0才開始有Property Animation相關的API。
2、所在包名不同:View Animation在包android.view.animation中。而Property Animation API在包 android.animation中。
3、動畫類的命名不同:View Animation中動畫類取名都叫XXXXAnimation,而在Property Animator中動畫類的取名則叫XXXXAnimator

大家都知道逐幀動畫主要是用來實現動畫的,而補間動畫才能實現控件的漸入漸出、移動、旋轉和縮放的;而Property Animator是在Android 3.0版本才引入的,之前是沒有的。大家可能會覺得補間動畫和逐幀動畫已經很全了,為什么還要引入Property Animator呢?

1、為什么引入Property Animator(屬性動畫)
我提出一個假設:請問大家,如何利用補間動畫來將一個控件的背景色在一分鐘內從綠色變為紅色?這個效果想必沒辦法僅僅通過改變控件的漸入漸出、移動、旋轉和縮放來實現吧,而這個效果是可以通過Property Animator完美實現的
這就是第一個原因:Property Animator能實現補間動畫無法實現的功能
大家都知道,補間動畫和逐幀動畫統稱為View Animation,也就是說這兩個動畫只能對派生自View的控件實例起作用;而Property Animator則不同,從名字中可以看出屬性動畫,應該是作用于控件屬性的!正因為屬性動畫能夠只針對控件的某一個屬性來做動畫,所以也就造就了他能單獨改變控件的某一個屬性的值!比如顏色!這就是Property Animator能實現補間動畫無法實現的功能的最重要原因。
我們得到了第二點不同:View Animation僅能對指定的控件做動畫,而Property Animator是通過改變控件某一屬性值來做動畫的。
假設我們將一個按鈕從左上角利用補間動畫將其移動到右下角,在移動過程中和移動后,這個按鈕都是不會響應點擊事件的。這是為什么呢?因為補間動畫僅僅轉變的是控件的顯示位置而已,并沒有改變控件本身的值。View Animation的動畫實現是通過其Parent View實現的,在View被drawn時Parents View改變它的繪制參數,這樣雖然View的大小或旋轉角度等改變了,但View的實際屬性沒變,所以有效區域還是應用動畫之前的區域;我們看到的效果僅僅是系統作用在按鈕上的顯示效果,利用動畫把按鈕從原來的位置移到了右下角,但按鈕內部的任何值是沒有變化的,所以按鈕所捕捉的點擊區域仍是原來的點擊區域。(下面會舉例來說明這個問題)
這就得到了第三點不同:補間動畫雖能對控件做動畫,但并沒有改變控件內部的屬性值。而Property Animator則是恰恰相反,Property Animator是通過改變控件內部的屬性值來達到動畫效果的

2、舉例說明補間動畫的點擊區域問題

下面我們就利用TranslateAnimation來做一個移動動畫的例子,看它的點擊區域是否會變。
我們先來看看效果


image.png

在效果圖中,首先,我給textview添加了點擊響應,當點擊textview時,會彈出Toast。
然后,當我點擊按鈕的時候,textview開始向右下角移動。
從結果中可以看出,在移動前,點擊textview是可以彈出toast的的,在移動后,點擊textview時則沒有響應,相反,點擊textview的原來所在區域則會彈出toast.

這就論證了不同第三點:補間動畫雖能對控件做動畫,但并沒有改變控件內部的屬性值

Android中常用的動畫都在這里了,包含了基本的動畫【透明度動畫,縮放動畫,旋轉動畫,位移動畫】;還有就是這四種動畫的組合實現; 還有布局動畫,就是在加載布局時的動畫;還有Activity跳轉的動畫。 效果圖如下:


a.gif

1. Android基礎動畫

如果是xml的方式寫要在res下創建anim文件夾內寫

透明度動畫

xml:

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

代碼:

        AlphaAnimation animation = new AlphaAnimation(0, 1);
        animation.setDuration(3000);
        animation.setFillAfter(true);
        mImg.setAnimation(animation);

縮放動畫

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:duration="1000"
        android:fromXScale="0"
        android:fromYScale="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1"
        android:toYScale="1" />
</set>

代碼:

 /**
 * 第一個參數fromX為動畫起始時 X坐標上的伸縮尺寸
 * 第二個參數toX為動畫結束時 X坐標上的伸縮尺寸
 * 第三個參數fromY為動畫起始時Y坐標上的伸縮尺寸
 * 第四個參數toY為動畫結束時Y坐標上的伸縮尺寸
 * 說明: 0.0表示收縮到沒有;1.0表示正常無伸縮;值小于1.0表示收縮;值大于1.
 * 第五個參數pivotXType為動畫在X軸相對于物件位置類型
 * 第六個參數pivotXValue為動畫相對于物件的X坐標的開始位置
 * 第七個參數pivotXType為動畫在Y軸相對于物件位置類型
 * 第八個參數pivotYValue為動畫相對于物件的Y坐標的開始位置
 */
    private void playAnimator(View view) {
        ObjectAnimator objectAnimatorX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f, 1.3f, 0.9f, 1.15f, 0.95f, 1.02f, 1.0f);
        ObjectAnimator objectAnimatorY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f, 1.3f, 0.9f, 1.15f, 0.95f, 1.02f, 1.0f);
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(objectAnimatorX).with(objectAnimatorY);
        animatorSet.setDuration(1000);
        animatorSet.start();
    }
Animation animation = new ScaleAnimation(0, 1
animation.setDuration(1000);
iv.startAnimation(animation);

旋轉動畫

<?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:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="360" />
</set>

代碼:

    /**
     * 第一個參數fromDegrees為動畫起始時角度
     * 第二個參數toDegrees為動畫結束角度
     * 第三個參數pivotXType為動畫在X軸相對于物件位置類型
     * 第四個參數pivotXValue為動畫相對于物件的X坐標的開始位置
     * 第五個參數pivotXType為動畫在Y軸相對于物件位置類型
     * 第六個參數pivotYValue為動畫相對于物件的Y坐標的開始位置
     */
    Animation animation = new RotateAnima
    animation.setDuration(1000);
    iv.startAnimation(animation);

位移動畫

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="2000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="500"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toYDelta="0" />
</set>

代碼:

    /**
     * 第一個參數fromDegrees為動畫起始時角度
     * 第二個參數toDegrees為動畫結束角度
     * 第三個參數pivotXType為動畫在X軸相對于物件位置類型
     * 第四個參數pivotXValue為動畫相對于物件的X坐標的開始位置
     * 第五個參數pivotXType為動畫在Y軸相對于物件位置類型
     * 第六個參數pivotYValue為動畫相對于物件的Y坐標的開始位置
     */
     Animation animation = new RotateAnima
     animation.setDuration(1000);
     iv.startAnimation(animation);
     /**
      * 第一個參數fromXDelta為動畫起始時的x坐標
      * 第二個參數toXDelta為動畫結束時的x坐標
      * 第三個參數fromYDelta為動畫起始時的y坐標
      * 第四個參數toYDelta為動畫結束時的y坐標
      */
      Animation animation = new Translat
      animation.setDuration(2000);
      /**設置插值器:先加速,后減速**/
      animation.setInterpolator(new Acce
      iv.startAnimation(animation);

2.組合動畫

先播放縮放動畫,完成后播放旋轉動畫

  Animation animation = AnimationUtils.loadAnimation(this, R.anim.scale);
               iv.startAnimation(animation);
               final Animation animation2 = AnimationUtils.loadAnimation(this, R.anim.rotate);
               animation.setAnimationListener(new Animation.AnimationListener() {
                   @Override
                   public void onAnimationStart(Animation animation) {

                   }

                   @Override
                   public void onAnimationEnd(Animation animation) {

                       iv.startAnimation(animation2);
                   }

                   @Override
                   public void onAnimationRepeat(Animation animation) {

                   }
               });

先播放旋轉動畫,完成后播放位移動畫,在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:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="360" />
    <translate
        android:duration="1000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:toXDelta="500"
        android:startOffset="1000"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toYDelta="0" />
</set>

重復的透明度動畫-閃爍

AlphaAnimation alphaAnimation = new AlphaAnimation(0.1f, 1.0f);
                alphaAnimation.setDuration(1000);
                alphaAnimation.setRepeatCount(10);
                /**倒序重復REVERSE  正序重復RESTART**/
                alphaAnimation.setRepeatMode(Animation.REVERSE);
                iv.startAnimation(alphaAnimation);

重復的位移動畫-抖動

 Animation translateAnimation = new TranslateAnimation(-10, 10, 0, 0);
                translateAnimation.setDuration(100);
                translateAnimation.setRepeatCount(10);
                /**倒序重復REVERSE  正序重復RESTART**/
                translateAnimation.setRepeatMode(Animation.REVERSE);
                iv.startAnimation(translateAnimation);

3.幀動畫

在drawable文件夾下建立文件

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
 >
   <item android:drawable="@mipmap/windmill_1"
       android:duration="500">
   </item>
   <item android:drawable="@mipmap/windmill_2"
       android:duration="500">
   </item>
   <item android:drawable="@mipmap/windmill_3"
       android:duration="500">
   </item>
   <item android:drawable="@mipmap/windmill_4"
       android:duration="500">
   </item>
   <item android:drawable="@mipmap/windmill_5"
       android:duration="500">
   </item>
   <item android:drawable="@mipmap/windmill_6"
       android:duration="500">
   </item>
   <item android:drawable="@mipmap/windmill_7"
       android:duration="500">
   </item>

</animation-list>

在activity中調用

   iv.setImageResource(R.drawable.ring_animation);
               AnimationDrawable animationDrawable = (AnimationDrawable) iv.getDrawable();
               animationDrawable.start();

4.布局動畫 這是一個ListView的加載布局動畫

先建立動畫文件,從透明到不透明并且大小從0到原大小

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator" >

    <scale
        android:duration="1000"
        android:fromXScale="0.1"
        android:fromYScale="0.1"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0" />
    <alpha
        android:duration="1000"
        android:fromAlpha="0"
        android:toAlpha="1.0" />
</set>

在activity中的用法

 ListView listView = (ListView) findViewById(R.id.listview);
        List<String> datas = new ArrayList<>();
        for (int i = 0; i < 18; i++) {
            datas.add("萬能適配器測試" + i);
        }
        LayoutAnimationController layoutAnimationController= new        LayoutAnimationController(AnimationUtils.loadAnimation(this, R.anim.zoom_in));
        layoutAnimationController.setOrder(LayoutAnimationController.ORDER_NORMAL);
        listView.setLayoutAnimation(layoutAnimationController);
        listView.setAdapter(new CommonAdapter<String>(this, datas, R.layout.item) {

            @Override
            protected void convertView(View item, String s) {
                TextView textView = CommonViewHolder.get(item, R.id.textView);
                textView.setText(s);
            }
        });

5.Activity跳轉動畫

退出動畫:從不透明到透明并且大小從原大小到0

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator"
    android:zAdjustment="top" >

    <scale
        android:duration="@android:integer/config_mediumAnimTime"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:pivotX="50%p"
        android:pivotY="50%p"
        android:toXScale="0.1"
        android:toYScale="0.1" />

    <alpha
        android:duration="@android:integer/config_mediumAnimTime"
        android:fromAlpha="1.0"
        android:toAlpha="0" />

</set>

進入動畫:從透明到不透明并且大小從0到原大小

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/decelerate_interpolator" >

    <scale
        android:duration="1000"
        android:fromXScale="0.1"
        android:fromYScale="0.1"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="1.0"
        android:toYScale="1.0" />
    <alpha
        android:duration="1000"
        android:fromAlpha="0"
        android:toAlpha="1.0" />
</set>

在Activity中的用法

  startActivity(new Intent(this,SecondActivity.class));
                overridePendingTransition(R.anim.zoom_in,R.anim.zoom_out);
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容