Android 動畫 介紹與使用

讀前思考

學習一門技術或者看一篇文章最好的方式就是帶着問題去學習,這樣才能在過程當中有茅塞頓開、燈火闌珊的感受,記憶也會更深入。java

  1. Android中有哪幾種類型的動畫?
  2. 幀動畫在使用時須要注意什麼?
  3. View動畫和屬性動畫的區別?
  4. View動畫爲什麼不能真正改變View的位置?而屬性動畫爲什麼能夠?
  5. 屬性動畫插值器和估值器的做用?

概述

在 Android 開發中,動畫是必不可少的,它可讓 View 在變化的時候有一個過渡,避免用戶感受很突兀。所以,學好動畫,用好動畫是很是重要的,會給開發帶來不少快樂。android

Android 中動畫分爲幀動畫、View 動畫、屬性動畫三種,能夠在平常開發中根據需求的不一樣進行選擇,但基本上如今 90% 以上的均可以用屬性動畫解決,如今讓咱們來了解一下三種動畫。bash

幀動畫

逐幀動畫是一種常見的動畫形式(Frame By Frame),其原理是在「連續的關鍵幀」中分解動畫動做,也就是在時間軸的每幀上逐幀繪製不一樣的內容,使其連續播放而成動畫。 由於逐幀動畫的幀序列內容不同,不但給製做增長了負擔並且最終輸出的文件量也很大,但它的優點也很明顯:逐幀動畫具備很是大的靈活性,幾乎能夠表現任何想表現的內容,而它相似與電影的播放模式,很適合於表演細膩的動畫。app

在 Android 中提供了兩種方式爲 AnimationDrawable 添加幀:XML 定義的資源文件和 Java 代碼建立。下面咱們會逐一進行介紹。框架

1. 使用 XML 定義的資源文件設置動畫幀

 Android 中的資源文件放在 /res 目錄下,對於動畫幀的資源須要當成一個 Drawable,因此須要把它放在 /res/Drawable 目錄下。而定義逐幀動畫很是簡單,在 drawable 文件夾下新建 xml 文件,在 <animation-list.../> 元素中使用 <item.../> 子元素定義動畫的所有幀,並制定各幀的持續時間便可。還能夠在 <animation-list.../> 元素中添加屬性,來設定逐幀動畫的屬性。ide

先上效果圖

XML幀動畫的資源文件:
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
<!-- 定義一個動畫幀,Drawable爲img0,持續時間50毫秒 -->
<item android:drawable="@drawable/uncheck_in1" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in2" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in3" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in4" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in5" android:duration="200"/>
<item android:drawable="@drawable/uncheck_in6" android:duration="200"/>
</animation-list>
複製代碼

Java 代碼使用動畫post

// 經過逐幀動畫的資源文件得到AnimationDrawable示例
AnimationDrawable frameAnim = (AnimationDrawable) getResources().getDrawable(R.drawable.part5_frame1);
// 把AnimationDrawable設置爲ImageView的背景
mImageView.setBackgroundDrawable(frameAnim);

/**
*根據點擊事件控制動畫開啓,中止
*/
@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.bt_start:
            frameAnim.start();
            break;
        case R.id.bt_stop:
            frameAnim.stop();
            break;
    }
}
複製代碼

2. 使用 Java 代碼建立逐幀動畫

在 Android 中,除了能夠經過 XML 文件定義一個逐幀動畫以外,還能夠經過 AnimationDrawable.addFrame() 方法爲 AnimationDrawable 添加動畫幀。
效果圖和上面的同樣,這裏就不放了,直接上代碼。學習

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_part5_frame_java);

    mImageView = findViewById(R.id.iv_frame1);
    Button bt_stop = findViewById(R.id.bt_stop);
    Button bt_start = findViewById(R.id.bt_start);
    bt_start.setOnClickListener(this);
    bt_stop.setOnClickListener(this);

    frameAnim = new AnimationDrawable();
    // 爲AnimationDrawable添加動畫幀
    frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in1), 200);
    frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in2), 200);
    frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in3), 200);
    frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in4), 200);
    frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in5), 200);
    frameAnim.addFrame(getResources().getDrawable(R.drawable.uncheck_in6), 200);
    frameAnim.setOneShot(false);

    mImageView.setBackground(frameAnim);

}

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.bt_start:
            if (frameAnim != null && !frameAnim.isRunning()) {
                frameAnim.start();
            }
            break;
        case R.id.bt_stop:
            if (frameAnim != null && frameAnim.isRunning()) {
                frameAnim.stop();
            }
            break;
    }

}
複製代碼

使用幀動畫的時候要注意不要使用過大的圖片,會引發 OOM。動畫

View 動畫

View 動畫框架只能用於 Views。 比較容易設置和能知足許多應用程序的須要。View 動畫框架中一共提供了 AlphaAnimation(透明度動畫)、RotateAnimation(旋轉動畫)、ScaleAnimation(縮放動畫)、TranslateAnimation(平移動畫)四種類型的補間動畫;而且 View 動畫框架還提供了動畫集合類(AnimationSet),經過動畫集合類(AnimationSet)能夠將多個補間動畫以組合的形式顯示出來。View 動畫只是顯示效果,View 的實際屬性及位置並未發生變化。ui

先看效果圖

在 /res 目錄下新建 anim 文件夾,在 anim 文件夾下新建 xml 文件

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- 透明度變化,從 1 到 0-->
    <alpha
        android:duration="5000"
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
    />
    <!-- 縮放,寬高都是從 1 到 0
         pivotX、pivotY 表明縮放中心點的橫豎座標
         interpolator 表明動畫模式,我設置爲先加速、後減速-->
    <scale
        android:duration="5000"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="0.0"
        android:toYScale="0.0"
    />
    <!-- 平移動畫,從左上角到右下角-->
    <translate
        android:duration="5000"
        android:fromXDelta="150"
        android:fromYDelta="150"
        android:toXDelta="200"
        android:toYDelta="200"/>
    <!-- 旋轉動畫,fromDegrees 初始角度
          結束角度 toDegrees-->
    <rotate
        android:duration="5000"
        android:fromDegrees="0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="+360"/>
</set>
複製代碼

在代碼中給 view 添加動畫

ImageView iv_bee=findViewById(R.id.iv_bee);
// 設置動畫資源
Animation loadAnimation =AnimationUtils.loadAnimation(this,R.anim.part5view_anim1);
//動畫結束後保持最後的狀態
loadAnimation.setFillAfter(true);
//給 view 添加動畫
iv_bee.startAnimation(loadAnimation);
複製代碼

屬性動畫

與屬性動畫相比 View 動畫存在一個缺陷,View 動畫改變的只是 View 的顯示,而沒有改變View的響應區域,而且 View 動畫只能對 View 作四種類型的補間動畫,所以在 Android3.0 及其後續版本中添加了屬性動畫框架。

屬性動畫理論知識有不少講解,能夠具體看下面的文章

HenCoder Android 自定義 View 1-6:屬性動畫 Property Animation(上手篇)

Android屬性動畫深刻分析:讓你成爲動畫牛人

我這裏就不講理論了,直接擼效果

一、 數字滾動效果

很簡單的一個數字滾動效果,用屬性動畫也很容易作出來,幾行代碼搞定

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_part5_object_anim);

    mTv_object = findViewById(R.id.tv_object);
    Button bt_start=findViewById(R.id.bt_start);
    bt_start.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showMoneyAnim(1,500);
        }
    });
}

private void showMoneyAnim(int mStartValue, int mEndValue) {
    ValueAnimator animator = ValueAnimator.ofInt(mStartValue, mEndValue);
    animator.setDuration(3000);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            mTv_object.setText(animation.getAnimatedValue().toString());
            }
        });
    animator.start();

    }
複製代碼
二、 簽到卡片翻轉效果

具體翻轉代碼,分爲上半段和下半段動畫

public class Part4AnimationActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_part4_animation);


        final ImageView iv_animation=findViewById(R.id.iv_animation);
        iv_animation.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                applyRotation(false,iv_animation,0,-90);
            }
        });
    }

    /**
     * 設置一個新的三維旋轉的容器視圖。只翻通常,而後設置新的現實內容
     *
     * @param zheng
     *            一個判斷機制 若是爲true 則向右翻轉,若是false則向左翻轉
     * @param view
     *            傳入的片斷
     * @param start
     *            起始位置
     * @param end
     *            結束位置
     */
public void applyRotation(final boolean zheng, final View view,
        final float start, final float end) {
        // Find the center of the container
        final float centerX = view.getWidth() / 2.0f;
        final float centerY = view.getHeight() / 2.0f;

        // Create a new 3D rotation with the supplied parameter
        // The animation listener is used to trigger the next animation
        final Util_Rotate3DAnimation rotation = new Util_Rotate3DAnimation(
                start, end, centerX, centerY, 310.0f, true);
        rotation.setDuration(500);
        rotation.setFillAfter(true);
        rotation.setInterpolator(new AccelerateInterpolator());
        rotation.setAnimationListener(new DisplayNextView(zheng, view));// 添加監聽執行現實內容的切換
        view.startAnimation(rotation);// 執行上半場翻轉動畫
    }

    /**
     * 執行完上半部分旋轉以後,設置要顯示的新的View而後繼續執行下半部分旋轉
     */
private final class DisplayNextView implements Animation.AnimationListener {
        private final boolean mPosition;
        private final View mView;

        private DisplayNextView(boolean zheng, View view) {
            mPosition = zheng;
            mView = view;
        }

        public void onAnimationStart(Animation animation) {
        }

        public void onAnimationEnd(Animation animation) {
            mView.post(new SwapViews(mPosition, mView));// 添加新的View
        }

        public void onAnimationRepeat(Animation animation) {
        }
    }
    /**
     * 添加要顯示的新的View,並執行下半部分的旋轉操做
     */
private final class SwapViews implements Runnable {
        private final boolean mPosition;
        private final ImageView mView;

        public SwapViews(boolean position, View view) {
            mPosition = position;
            mView = (ImageView) view;
        }

        public void run() {
            final float centerX = mView.getWidth() / 2.0f;
            final float centerY = mView.getHeight() / 2.0f;
            Util_Rotate3DAnimation rotation;

            if (mPosition) {
                rotation = new Util_Rotate3DAnimation(-90, 0, centerX, centerY,
                        310.0f, false);
            } else {
                rotation = new Util_Rotate3DAnimation(90, 0, centerX, centerY,
                        310.0f, false);
            }
            mView.setImageResource(R.drawable.head2);

            rotation.setDuration(500);
            rotation.setFillAfter(true);
            rotation.setInterpolator(new DecelerateInterpolator());
            mView.startAnimation(rotation);
        }
    }

}
複製代碼

文章已經讀到末尾了,不知道最初的幾個問題你都會了嗎?若是不會的話?能夠再針對不會的問題進行精讀哦!答案都在文中,相信你確定能夠解決的!

相關文章
相關標籤/搜索