Android動畫全解

来源:http://www.cnblogs.com/shouce/archive/2016/06/08/5569190.html
-Advertisement-
Play Games

在Android開發中經常會碰到動畫,看到別的應用有很酷炫的應用時,總是想怎麼去實現,但是每次都是發現感覺是知道怎麼做的,實際做起來還是無從下手的感覺,究其原因還是 Android動畫方面的知識不全面,這幾天利用空閑時間研究了下Android動畫知識,當作學習日記,大家也好有所借鑒。 Android ...


在Android開發中經常會碰到動畫,看到別的應用有很酷炫的應用時,總是想怎麼去實現,但是每次都是發現感覺是知道怎麼做的,實際做起來還是無從下手的感覺,究其原因還是

Android動畫方面的知識不全面,這幾天利用空閑時間研究了下Android動畫知識,當作學習日記,大家也好有所借鑒。

Android主要分三類動畫:Tween Animation、Frame Animation、Property Animation。

其中Tween Animation、Frame Animation是在Android是在Android3.0之前就有的動畫技術,後來由於動畫需求越來越高,Tween Animation、Frame Animation已經滿足不了應用對於動畫效果的需求了,於是在Android3.0之後,谷歌又增加了新的動畫Property Animation。下麵對這三種動畫逐個介紹。

 

一、Tween Animation

中文亦叫補間動畫,它是通過平移、旋轉、縮放以及修改透明度來達到動畫效果的,原理是給出兩個關鍵幀,通過一些演算法將給定屬性值在給定時間內在兩個關鍵幀間漸變。這裡我們只關心動畫的使用,不關註它的代碼實現。Tween Animation基於Animation類擴展,有以下幾個Tween Animation類:TranslateAnimation(平移)、AlphaAnimation(透明度)、ScaleAnimation(縮 放)、RotateAnimation(旋轉)。

TranslateAnimation使用方法如下:

複製代碼
private TranslateAnimation mTranslateAnimation;
//這四個參數含義分別是當前View x起點坐標、x終點坐標、y起點坐標、y終點坐標
mTranslateAnimation = new TranslateAnimation(0, 200, 0, 0);
//動畫持續時間
mTranslateAnimation.setDuration(2000);
//重覆次數
mTranslateAnimation.setRepeatCount(1);
//動畫執行模式
mTranslateAnimation.setRepeatMode(Animation.REVERSE);
複製代碼

以上代碼含義為從view的起點開始,保持y軸不變,沿著x平移200個像素,平移時間為2秒,重覆執行一次,第二次執行方式與第一次執行方式完全相反,如下圖:

以上是java代碼實現的方式,亦可以使用xml實現,如下:

/res/anim/translate.xml

複製代碼
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:fromXDelta="0"
        android:toXDelta="200"
        android:fromYDelta="0"
        android:toYDelta="0"
        android:duration="2000"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"/>
</set>
複製代碼

fromXDelta:View x軸起點

toXDelta:View x軸終點

fromYDelta:View y軸起點

toYDelta:View y軸終點

duration:動畫持續時間

repeatCount:動畫執行次數

repeatMode:動畫執行模式

interpolator:插值器,可以理解為View動畫值的改變規律

java中調用:

private Animation mTranslateAnimation;
mTranslateAnimation = AnimationUtils.loadAnimation(this, R.anim.translate);
mTranslateIv.startAnimation(mTranslateAnimation);

使用Java或者xml實現動畫並無什麼不同,採用哪種完全取決於自己的編程習慣,但如果單純從擴展性來說,顯然xml方式更占優。

AlphaAnimation使用方法如下:

private AlphaAnimation mAlphaAnimation;
//不透明度從100%到0
mAlphaAnimation = new AlphaAnimation(1, 0);
mAlphaAnimation.setDuration(2000);
mAlphaAnimation.setRepeatCount(1);
mAlphaAnimation.setRepeatMode(Animation.REVERSE);

以上代碼含義是在2秒內將View的不透名度從1變為0,總共執行2次,第一次和第二次執行動畫過程相反,效果如下圖:

xml實現方法可參照TranslateAnimation

ScaleAnimation使用方法如下:

mScaleAnimation = new ScaleAnimation(1, 2, 1, 2);
mScaleAnimation.setDuration(2000);
mScaleAnimation.setRepeatCount(1);
mScaleAnimation.setRepeatMode(Animation.REVERSE);

上面ScaleAnimation構造函數中四個參數分別是:

fromX:起始x方向大小

toX:最終x方向大小

fromY:起始y坐標

toY:最終y坐標

上面代碼含義為將View在2秒內橫豎方向增大一倍,第二次是在原來的基礎上縮小一倍,效果圖如下:

xml實現方法同參照TranslateAnimation

RotateAnimation使用方法如下:

mRotateAnimation = new RotateAnimation(0, 360);
mRotateAnimation.setDuration(2000);
mRotateAnimation.setRepeatCount(1);
mRotateAnimation.setRepeatMode(Animation.REVERSE);

上面代碼含義為在2秒內將View旋轉360度,再旋轉回來,效果如下:

 

二、Frame Animation

看過電影的人也許知道,電影是由一張一張圖片組成的,只不過圖片切換速度快,在人視覺中看到的是連續效果。Frame Animation亦同樣基於此原理實現,事先準備幾張圖片,按特定的順序排好,然後使用特定的動畫類將其播放,基於這種動畫實現方式,Frame Anmation亦有一個中文名:逐幀動畫。

實現這種動畫需要使用到AnimationDrawable類,它繼承於Drawable,使用方式如下:

複製代碼
private AnimationDrawable mAnimationDrawable;
mAnimationDrawable = new AnimationDrawable();
//增加圖片,並設定圖片播放時間
mAnimationDrawable.addFrame(getResources().getDrawable(R.drawable.australia), 500);
mAnimationDrawable.addFrame(getResources().getDrawable(R.drawable.austria), 500);
mAnimationDrawable.addFrame(getResources().getDrawable(R.drawable.china), 500);
mAnimationDrawable.start();
複製代碼

上面代碼是將三張圖片按照指定的順序,指定的時間播放,以達到動畫效果,如下圖:

同樣亦可以使用xml方式實現,代碼如下:

/anim/frame.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/australia" android:duration="500"/>
    <item android:drawable="@drawable/austria" android:duration="500"/>
    <item android:drawable="@drawable/china" android:duration="500"/>
</animation-list>
複製代碼

xml中調用:

<ImageView
        android:id="@+id/frame_iv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@anim/frame"/>

java中調用:

private ImageView mFrameIv;
private AnimationDrawable mAnimationDrawable;
mFrameIv = (ImageView) findViewById(R.id.frame_iv);
mAnimationDrawable = (AnimationDrawable) mFrameIv.getBackground();
mAnimationDrawable.start();

關於Frame Tween的知識比較簡單,熟悉AnimationDrawable便行,下麵介紹本章最重要的Property Animation。

 

三、Property Animation

中文亦叫屬性動畫,如其名字一樣,可以改變對象的屬性,註意是對象,不是View,而且是任意對象,只要對象符合一定條件即可,上述中的Tween Animation僅僅只能操作View,對於View之外的對象則無能為力,並且其未改變View的屬性,僅僅是通過父類View對其重繪達到動畫效果;而Frame Animation動畫功能則過於簡單。隨著我們Android應用的發展,能發現Tween Animation、Frame Animation有時候並不能達到理想的效果,谷歌亦意識到了這點,故而在Android3.0之後增加了強大的屬性動畫。

Property Animation有兩個類可供使用:ValueAnimator、ObjectAnimator。這兩個類均直接或間接繼承於Animator

ObjectAnimator使用方式如下:

複製代碼
private ObjectAnimator mObjectAnimator;
//設置不透明度從1到0變化
mObjectAnimator = ObjectAnimator
                .ofFloat(mObjectAnimatorIv, "alpha", 1, 0)
                .setDuration(1000);
//設置插值器,先加速後減速
mObjectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
//動畫重覆執行一次
mObjectAnimator.setRepeatCount(1);
//設置執行模式
mObjectAnimator.setRepeatMode(ValueAnimator.REVERSE);
mObjectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        //獲取當前的動畫值
        float cVal = (Float) animation.getAnimatedValue();
        //根據動畫值縮放當前View
        mObjectAnimatorIv.setScaleX(cVal);
        mObjectAnimatorIv.setScaleY(cVal);
    }
});
複製代碼

上面代碼意思是將當前View不透明度從1按照一定規律變為0,第一句代碼中的ofFloat(mObjectAnimatorIv, "alpha", 1, 0)中的alpha代表不透明度,有人可能會說我可以寫其他的嗎?當然可以,比如寫成ofFloat(mObjectAnimatorIv, "tmg", 1, 0),但你會發現動畫執行後不會有效果,因為寫這個字元串的前提是當前View或者當前View的父類中實現了這個字元串的get、set方法,即getAlpha、setAlpha,當動畫執行時,動畫類會通過調用setAlpha來改變View的alpha屬性,達到想要的動畫效果。那這個alpha是怎麼從1便到0的呢?Property Animation中有一個TypeEvaluator,這個屬性的含義是根據屬性的開始、結束值與TimeInterpolation計算出的因數計算出當前時間的屬性值,上例中的alpha便是這樣從1變到0的,但是上面並沒設置TypeEvaluator啊?其原因是Property Animation

會配置一個預設的TypeEvaluator,如果一定要顯性設置,有幾個寫好的TypeEvaluator供選擇:

IntEvaluator:屬性值的類型為int

FloatEvaluator:屬性值的類型為float

ArgbEvaluator:屬性的值類型為十六進位顏色值

如果上述沒有你需要的TypeEvaluator,你亦可以選擇繼承TypeEvaluator自定義一個類似的TypeEvaluator

從上面代碼中我們還可以看到:

float cVal = (Float) animation.getAnimatedValue();
mObjectAnimatorIv.setScaleX(cVal);
mObjectAnimatorIv.setScaleY(cVal);

其中animation.getAnimatedValue();是計算View當前屬性值,當然根據前面的設置,這個屬性值實在1到0之間變化,下麵的兩行代碼是通過每個時刻不同的屬性值對View進行縮放,達到在改變透明度的同時,

又改變View大小的效果,效果圖如下:

同樣的,Property Animation也可以通過xml實現,類似上面兩種,不再介紹,讀者可從之後分享的源碼中看到

ValueAnimator的使用方式和ObjectAnimator很相似,唯一的區別是ValueAnimator不能直接設置屬性,即類似

mObjectAnimator = ObjectAnimator
                .ofFloat(mObjectAnimatorIv, "alpha", 1, 0)
                .setDuration(1000);

它只能這樣:

mValueAnimator = ValueAnimator.ofFloat(1, 0);
mValueAnimator.setTarget(mValueAnimatorIv);

動畫效果可在監聽事件中實現,如:

複製代碼
mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float animatedValue = (float) animation.getAnimatedValue();
        mValueAnimatorIv.setAlpha(animatedValue);
        mValueAnimatorIv.setScaleX(animatedValue);
        mValueAnimatorIv.setScaleY(animatedValue);
    }
});
複製代碼

談談Keyframe,keyframe是一個時間/值對,通過它可以定義一個在特定時間的特定狀態,

即關鍵幀,而且在兩個keyframe之間可以定義不同的Interpolator,就好像多個動畫的拼接,第一個動畫的結束點是第二個動畫的開始。keyframe是抽象類,要通過ofInt(),ofFloat()等獲得適當的keyframe,然後通過PropertyValuesHolder.ofKeyframe

獲得PropertyValuesHolder對象,如下例子:

複製代碼
Keyframe kf0 = Keyframe.ofInt(0, 400);
Keyframe kf1 = Keyframe.ofInt(0.25f, 200);
Keyframe kf2 = Keyframe.ofInt(0.5f, 400);
Keyframe kf3 = Keyframe.ofInt(0.75f, 100);
Keyframe kf4 = Keyframe.ofInt(1f, 500);
PropertyValuesHolder propertyValuesHolder = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf3, kf4);
mKeyframesObjectAnimator = ObjectAnimator.ofPropertyValuesHolder(mKeyframesObjectAnimationBtn, propertyValuesHolder);
mKeyframesObjectAnimator.setDuration(2000);
mKeyframesObjectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        android.util.Log.d("update", (animation.getAnimatedValue()).toString());
    }
});
複製代碼

動畫效果同樣是在onAnimationUpdate中添加,上面僅僅是打個log

如果你想應用多個動畫,AnimationSet可以幫到你,AnimationSet提供了一個把多個動畫組合成一個組合的機制,並可設置組中動畫的時序關係,如同時播放,順序播放等。

如下代碼:

mAnimatorSet = new AnimatorSet();
mAnimatorSet.play(mObjectAnimator).before(mValueAnimator);
mAnimatorSet.play(mValueAnimator).before(mKeyframesObjectAnimator);

play是播放,before是在當前動畫之前播放,還有2個方法with、after,分別是與當前動畫同時播放,在當前動畫之後播放,效果如下:

上面是三個動畫按照一定順序播放,有時候我們需要比較複雜的動畫效果時,這個類會很重要。

 

四、擴展介紹

interpolator:插值器,代表動畫值的變化速度

repeatCount:動畫重覆執行的次數

repeatMode:動畫執行模式,每次動畫執行方式是一樣還是按照相反方向執行

duration:動畫執行時間

evaluator:根據屬性的開始、結束值與TimeInterpolation計算出的因數計算出當前時間的屬性值

 

參考文章:

http://www.cnblogs.com/angeldevil/archive/2011/12/02/2271096.html

http://blog.csdn.net/lmj623565791/article/details/38092093

源碼:

https://github.com/taothreeyears/animation

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 函數的四種存在形態: 1.函數形態 2.方法形態 將函數賦值給某一個對象的成員,那麼就稱為方法 3.構造器形態 4.上下文形態 1.函數形態: var foo = function() { alert(this); //this是window }; 2.方法形態: o = {}; o.foo = f ...
  • 概述 當我們在談論面向對象編程時,我們在談論什麼?我們首先談論的是一些概念:對象、類、封裝、繼承、多態。對象和類是面向對象的基礎,封裝、繼承和多態是面向對象編程的三大特性。 JavaScript提供了對象卻缺乏類,它不能像C#一樣能顯式地定義一個類。但是JavaScript的函數功能非常靈活,其中之... ...
  • ...
  • E:first-child解釋:E的父元素的第一個子元素正好是E,給這個E定義樣式 E:last-child解釋:E的父元素的最後一個子元素正好是E,給這個E定義樣式 E:only-child解釋:E的父元素只有一個子元素,這個正好是E,給這個E定義樣式 E:empty解釋:E元素沒有子元素和文本內 ...
  • 今天在製作焦點輪播圖的時候,遇到一個問題,在使用style.left獲取圖片的位置時,怎麼也獲取不到。換用offsetLeft就能夠成功獲取到了。雖然實現了我想要的效果,但是還是不甘心啊,沒有找到原因,心裡就是怪怪的,於是我翻開JavaScript高級程式設計,將style.left和offsetL ...
  • CSS3 target 偽類不得不說那些事兒(純CSS實現tab切換) CSS3 target 偽類不得不說那些事兒(純CSS實現tab切換) 是不是覺得target有點眼熟?! 今天要講的不是HTML的<a>標簽裡面有個target屬性。 target偽類是css3的新屬性。 說到偽類,對css屬 ...
  • Activity: String myArguments; public String getarguments() { return myArguments; } public void setarguments(String title) { this.myArguments = title; ...
  • 要實現地圖、導航功能,往往需要先熟悉定位功能,在iOS中通過Core Location框架進行定位操作。Core Location自身可以單獨使用,和地圖開發框架MapKit完全是獨立的,但是往往地圖開發要配合定位框架使用。在Core Location中主要包含了定位、地理編碼(包括反編碼)功能。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...