1. 程式人生 > >android之逐幀,補間動畫詳解。

android之逐幀,補間動畫詳解。

在android的世界中有三種動畫,它們就是逐幀動畫,補間動畫,屬性 動畫。接下來我就分別演示下三種動畫的簡單用法。

各動畫的定義:

  1. 逐幀動畫:就是短時間切換圖片,讓人們肉眼看起來是連續的,其實就是播放一組圖片。就相當於gif圖片的生成、還有我們小時候看電影的時候。那時是通過切換膠片來達到放電影。我是農村的,小時候經常看到。不知道你們有木有經歷過。。。
  2. 補間動畫:就是操作某個控制元件讓其展現出旋轉、漸變、移動、縮放的這麼一種轉換過程,我們稱為補間動畫。我們也可以XML形式定義動畫,也可以java程式碼實現。
  3. 屬性動畫:這個是Android3.0才出現的。它彌補了以前補間動畫的一些缺陷。它是通過改變物件的屬性來進行的。

逐幀動畫的使用

在res/drawable下建立個anni.xml程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item
        android:drawable="@drawable/huan"
        android:duration="200" />
    <item
        android:drawable
="@drawable/yin" android:duration="200" />
<item android:drawable="@drawable/ni" android:duration="200" /> <item android:drawable="@drawable/lai" android:duration="200" /> <item android:drawable="@drawable/dao" android:duration
="200" />
<item android:drawable="@drawable/wo" android:duration="200" /> <item android:drawable="@drawable/de" android:duration="200" /> <item android:drawable="@drawable/bo" android:duration="200" /> <item android:drawable="@drawable/ke" android:duration="200" /> </animation-list>

android:oneshot false代表的是無限迴圈,true代表的是隻迴圈一次。不寫的話預設是false

main_activity.xml程式碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.edu.animsimple.MainActivity">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:onClick="onclick"
        android:text="逐幀動畫"
        />

    <ImageView
        android:id="@+id/img"
        android:src="@drawable/anni"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />
</LinearLayout>

我們就已經為這張圖片引用動畫了,執行結果為:

這裡寫圖片描述

我們也可以不在xml中寫android:src=”@drawable/anni” 可以在程式碼中寫。

MainActivity程式碼如下:

import android.graphics.drawable.AnimationDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    private ImageView mImg;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mImg= (ImageView) findViewById(R.id.img);

    }

    /**
     * 逐幀動畫
     * @param view
     */
    public void onclick(View view) {
        mImg.setImageResource(R.drawable.zhuzhen);//為該圖片設定動畫
        AnimationDrawable animationDrawable= (AnimationDrawable) mImg.getDrawable();//獲取drawable物件
        animationDrawable.start();//開啟動畫
         //animationDrawable.stop();//停止動畫
    }

}

點選按鈕後,執行結果:
這裡寫圖片描述

好了,逐幀動畫就是這麼點內容。

補間動畫

我們先看下補間動畫的用法:
- AlphaAnimation:透明度(alpha)漸變效果,對應alpha標籤。
- TranslateAnimation:位移漸變,需要指定移動點的開始和結束座標,對應translate標籤。
- ScaleAnimation:縮放漸變,可以指定縮放的參考點,對應scale標籤。
- RotateAnimation:旋轉漸變,可以指定旋轉的參考點,對應rotate標籤。
- AnimationSet:組合漸變,支援組合多種漸變效果,對應set標籤。

既可以在xml中寫,也可以在java程式碼中寫,下面就兩種情況都演示下吧

在res/anim目錄下建立個alpha.xml程式碼如下:

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

android:fromAlpha=”1.0”表示的是完全不透明。
android:toAlpha=”0.0”表示的是完全透明。
android:duration=”2000”表示的是時長。
android:fillAfter=”true”表示的是動畫結束時停在那。

在res/anim目錄下建立個translate .xml程式碼如下:

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

android:fromXDelta=”100%”表示的x點是從相對於自己左邊緣x座標一倍地方開始。
android:fromYDelta=”100%”表示的是y點是相對於自己左邊緣y座標一倍地方開始
android:toXDelta=”0%”表示x點的是相對於自己左邊緣x軸結束
android:toYDelta=”0%”表示的是y點從哪相對於自己左邊緣y軸結束
android:duration=”2000”表示的是動畫時長
android:fillAfter=”true”表示的是動畫結束時,停在那,
android:interpolator=”@android:anim/accelerate_decelerate_interpolator表示的是動畫過程中是先加速後減速。

android:fromXDelta這樣的屬性值有三種寫法,就以這種屬性情況解釋下,其他都一樣;

  1. android:fromXDelta=“200” 就是確定的值,表示的是就是從這x座標開始
  2. android:fromXDelta=“200%”表示的是相對於自身控制元件而言的
  3. android:fromXDelta=“200%p”這個表示的是相對於父容器而言的。

第一種情況很好理解,就是從給定的位置開始動畫

第二種情況,也比較好理解。給個例子吧。一個按鈕,點選按鈕發生動畫。如下圖:
這裡寫圖片描述

第三情況也不太難理解。還是給張圖比較好理解:

這裡寫圖片描述

在res/anim目錄下建立個scale .xml程式碼如下:

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

android:pivotX=”50%”
android:pivotY=”50%”
這個表示的是相對於自身而言,50%,50%表示的就是以自身的中心點縮放。
如果是具體的值,比如50,50,就是相對於自身控制元件的左邊緣50,上邊緣50進行縮放。
如果是50%p,50%p那就是相對於父控制元件進行縮放。。其他的都比較好理解,就不說了。 比如 android:fromXScale=”1” ,android:toXScale=”2”表示的是x放大兩倍。

在res/anim目錄下建立個 rotate.xml程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="3000"
    >
</rotate>

android:fromDegrees=”0” 表示的是從0度開始
android:toDegrees=”360” 表示的是旋轉360度結束
android:pivotX=”50%” 相對於自身而言
android:pivotY=”50%” 相對於自身而言
android:duration=”3000” 動畫時間

android:pivotX="50%"  
android:pivotY="50%" 
 這跟上面縮放的意思是一樣的。也有三種情況。具體值,相對於自己,相對於父容器。了。

在res/anim目錄下建立個 set.xml程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="5000"
    android:shareInterpolator="true"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:repeatMode="reverse"
    >

    <!--透明度動畫-->
    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:duration="2000"
        android:fillAfter="true"
        />
    <!--位移動畫-->
    <translate
        android:fromXDelta="100%"
        android:fromYDelta="100%"
        android:toXDelta="0%"
        android:toYDelta="0%"
        android:duration="2000"
       />

    <!--旋轉動畫-->
    <rotate
        android:fromDegrees="0"
        android:toDegrees="360"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="3000"
        />
    <!--縮放動畫-->
    <scale
        android:fromXScale="1"
        android:toXScale="2"
        android:fromYScale="1"
        android:toYScale="2"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration="3000"
        />
</set>

組合動畫就是把這些動畫組合在一起,其實也沒什麼。上面的沒出現過的幾個屬性說下吧。
android:shareInterpolator=”true” true表示的是都是共享一個插值器。
android:repeatMode=”reverse” reverse表示的是迴圈重複。

接下來就執行下:

activity_main.xml程式碼如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.edu.animsimple.MainActivity">

    <Button
        android:id="@+id/alpha"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="透明度動畫"
        />

    <Button
        android:id="@+id/translate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="位移動畫"
        />

    <Button
        android:id="@+id/scale"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="縮放動畫"
        />

    <Button
        android:id="@+id/rotate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="旋轉動畫"
        />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/set"
        android:text="組合動畫"
        />
</LinearLayout>

MainActivity.java程式碼如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button alphaBtn ,translateBtn,scaleBtn,rotateBtn,setBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        alphaBtn= (Button) findViewById(R.id.alpha);
        translateBtn= (Button) findViewById(R.id.translate);
        scaleBtn= (Button) findViewById(R.id.scale);
        rotateBtn= (Button) findViewById(R.id.rotate);
        setBtn= (Button) findViewById(R.id.set);
        alphaBtn.setOnClickListener(this);
        translateBtn.setOnClickListener(this);
        scaleBtn.setOnClickListener(this);
        rotateBtn.setOnClickListener(this);
        setBtn.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.alpha:
                Animation alpha= AnimationUtils.loadAnimation(this,R.anim.alpha);
                alphaBtn.startAnimation(alpha);
                break;
            case R.id.translate:
                Animation translate= AnimationUtils.loadAnimation(this,R.anim.translate);
                translateBtn.startAnimation(translate);
                break;
            case R.id.scale:
                Animation scale= AnimationUtils.loadAnimation(this,R.anim.scale);
                scaleBtn.startAnimation(scale);
                break;
            case R.id.rotate:
                Animation rotate= AnimationUtils.loadAnimation(this,R.anim.rotate);
                rotateBtn.startAnimation(rotate);
                break;
            case R.id.set:
                Animation set= AnimationUtils.loadAnimation(this,R.anim.set);
                setBtn.startAnimation(set);
                break;
        }
    }
}

執行結果:

這裡寫圖片描述

通過xml的方式實現學習完了,接下來怎麼通過java程式碼實現:

MainActivity.java程式碼如下:

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.view.animation.ScaleAnimation;
import android.view.animation.TranslateAnimation;
import android.widget.Button;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button alphaBtn, translateBtn, scaleBtn, rotateBtn, setBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        alphaBtn = (Button) findViewById(R.id.alpha);
        translateBtn = (Button) findViewById(R.id.translate);
        scaleBtn = (Button) findViewById(R.id.scale);
        rotateBtn = (Button) findViewById(R.id.rotate);
        setBtn = (Button) findViewById(R.id.set);
        alphaBtn.setOnClickListener(this);
        translateBtn.setOnClickListener(this);
        scaleBtn.setOnClickListener(this);
        rotateBtn.setOnClickListener(this);
        setBtn.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.alpha:
                /**
                 * 這是通過xml實現的
                 */
//                Animation alpha= AnimationUtils.loadAnimation(this,R.anim.alpha);
//                alphaBtn.startAnimation(alpha);
                /**
                 * 這是通過java程式碼實現的,跟xml實現的效果一樣
                 */
                AlphaAnimation alpha = new AlphaAnimation(1.0f, 0.0f);
                alpha.setDuration(2000);
                alpha.setFillAfter(true);
                alphaBtn.startAnimation(alpha);
                break;
            case R.id.translate:
                /**
                 * 這是通過xml實現的
                 */
//                Animation translate= AnimationUtils.loadAnimation(this,R.anim.translate);
//                translateBtn.startAnimation(translate);
                /**
                 * 通過java程式碼實現,跟xml實現的效果一樣
                 */
                TranslateAnimation translate = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
                        1.0f, Animation.RELATIVE_TO_SELF, 0.0f,
                        Animation.RELATIVE_TO_SELF,
                        1.0f, Animation.RELATIVE_TO_SELF, 0.0f
                );
                translate.setDuration(2000);
                translate.setInterpolator(new AccelerateDecelerateInterpolator());
                translateBtn.startAnimation(translate);
                break;
            case R.id.scale:
                /**
                 * 這是通過xml實現的
                 */
//                Animation scale= AnimationUtils.loadAnimation(this,R.anim.scale);
//                scaleBtn.startAnimation(scale);
                /**
                 * 通過java程式碼實現,跟xml實現的效果一樣
                 */
                ScaleAnimation scale = new ScaleAnimation(1.0f, 2.0f, 1.0f, 2.0f,
                        Animation.RELATIVE_TO_SELF, 0.5f,
                        Animation.RELATIVE_TO_SELF, 0.5f
                );
                scale.setDuration(3000);
                scaleBtn.startAnimation(scale);
                break;
            case R.id.rotate:
                /**
                 * 這是通過xml實現的
                 */
//                Animation rotate= AnimationUtils.loadAnimation(this,R.anim.rotate);
//                rotateBtn.startAnimation(rotate);
                /**
                 * 通過java程式碼實現,跟xml實現的效果一樣
                 */
                RotateAnimation rotate = new RotateAnimation(0.0f, 360.0f
                        , Animation.RELATIVE_TO_SELF, 0.5f,
                        Animation.RELATIVE_TO_SELF, 0.5f
                );
                rotate.setDuration(3000);
                rotateBtn.startAnimation(rotate);
                break;
            case R.id.set:
                /**
                 * 這是通過xml實現的
                 */
//                Animation set = AnimationUtils.loadAnimation(this, R.anim.set);
//                setBtn.startAnimation(set);
                /**
                 * 通過java程式碼實現,只實現了兩種動畫的組合。
                 */
                RotateAnimation rotateSet = new RotateAnimation(0.0f, 360.0f
                        , Animation.RELATIVE_TO_SELF, 0.5f,
                        Animation.RELATIVE_TO_SELF, 0.5f
                );
                TranslateAnimation translateSet = new TranslateAnimation(Animation.RELATIVE_TO_SELF,
                        1.0f, Animation.RELATIVE_TO_SELF, 0.0f,
                        Animation.RELATIVE_TO_SELF,
                        1.0f, Animation.RELATIVE_TO_SELF, 0.0f
                );
                AnimationSet  set=new AnimationSet(true);
                set.setDuration(5000);
                set.setInterpolator(new LinearInterpolator());
                set.addAnimation(rotateSet);
                set.addAnimation(translateSet);
                set.setRepeatMode(Animation.REVERSE);//啟動模式
                setBtn.startAnimation(set);
                break;
        }
    }
}

執行效果是一樣的。就不給出來額。xml跟java程式碼實現效果是一樣的。這個就看個人愛好了,我是比較喜歡通過java程式碼實現。

到這裡已經把逐幀動畫跟補間動畫學完了。還有屬性動畫就留在明天寫了,這篇有點長了。

總結:

我也是名初學者,寫部落格主要是回顧下自己學的東西,你認為不對的地方請大膽指正。謝謝。