愛她就要了解她之Android動畫

在Android中的動畫主要有四種形式
1.Tween Aniamtion(變換動畫)
2.Property Animation(屬性動畫)
3.Layout Animation(布局動畫)
4.Frame Animation(逐幀動畫)
在我們的應用中適當地使用動畫,可以讓我們的應用更加美觀、柔和,對用戶來說也會更加友好。

Tween Aniamtion

Tween Animation分為四種:
Alpha:漸變透明度動畫
Scale:漸變尺寸縮放動畫
Translate:位置移動變換動畫
Rotate:旋轉動畫
共同屬性:
(1)duration:動畫持續時間。單位:毫秒
(2)reaptCount:動畫重復次數
(3)reaptMode:動畫重復模式(值:倒序重復 REVERSE,順序重復 RESTART)
(4)startOffset:動畫之間的時間間隔
(5)fillAfter:設置為true,表示動畫轉化效果在動畫結束后被應用
(6)fillBefore:設置為true,表示動畫轉化效果在動畫開始前被應用
(7)interprolator:動畫插入器(加速、減速插入器)
以上的共同屬性都可以通過set方式進行設置。
下面對這四種動畫類型一一介紹
我們首先初始化一個View,以便下面演示

ImageView img = new ImageView(this)

1.Alpha

對view的透明度進行設置的取值范圍是0.0~1.0
0.0表示完全透明 1.0表示完全不透明
Java Code:

AlphaAnimation alpha = new AlphaAnimation(0F,1F);

該構造方法中的第一個參數是初始透明度,第二個參數是最終透明度。

alpha.setDuration(1000)//設置持續時間

最后使用Vew的startAnimation()方法開始執行動畫

img.startAnimation(alpha)//開始執行動畫

XML配置文件
在xml中編寫動畫代碼,需要在工程中的res目錄下添加anim目錄,然后在該目錄中新建一個xml文件,然后如下編寫:

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0"
    android:toAlpha="1"
    android:duration="1000">
</alpha>

然后在Java Code中使用AnimationUtils類的loadAnimation(Context context, int id)將xml中的動畫文件加載進來。同樣對于View使用startAnimation()方法即可

2.Scale

對View縮放的取值范圍是從0~
0表示消失 1表示不縮放 >1表示放大
Java Code
ScaleAnimation有三個構造方法:

public ScaleAnimation(float fromX, float toX, float fromY, float toY)//前兩個參數是ViewX方向的縮放,后兩個參數是ViewY方向的縮放
public ScaleAnimation(float fromX, float toX, float fromY, float toY,float pivotX, float pivotY)//前四個參數和第一個構造方法一樣,最后兩個參數是縮放的中心點
public ScaleAnimation(float fromX, float toX, float fromY, float toY,int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)

對于第三個構造方法中前四個參數和第一個構造方法一樣,后面四個參數:pivotXType與pivotYType指縮放中心點的類型,其值在Animation類中有定義:

RELATIVE_TO_SELF//指相對自身設置縮放中心
RELATIVE_TO_PARENT//指相對于view的父View設置縮放中心
ABSOLUTE//絕對的

最后的兩個參數需使用百分比的方式設置縮放中心,即值為0~1F。
XML配置文件

<scale xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXScale="0"
    android:toXScale="1"
    android:fromYScale="0"
    android:toYScale="1"
    android:pivotX="50%"
    android:pivotY="50%"
    android:duration="1000">
</scale>

使用XML文件配置動畫時,pivotX與pivotY既可以使用百分比方式,也可以使用dp方式

3.Translate

Java Code
Translate有兩個構造方法:

public TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)//很容易理解,即X方向的移動距離,Y方向的移動距離
public TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue, 
                          int fromYType, float fromYValue, int toYType, float toYValue)

第二個構造方法中的fromXType與fromYType與ScaleAnimation中的pivotXType的值是一樣的,默認為相對自身的當前位置,其他參數與第一個構造方法的參數含義一樣
XML配置文件

<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromXDelta="0"
    android:toXDelta="100"
    android:fromYDelta="0"
    android:toYDelta="100"
    android:duration="1000">
</translate>

比較簡單,就不做詳細介紹了。

4.Rotate

Java Code
RotateAnimation也有三個常用的構造方法:

public RotateAnimation(float fromDegrees, float toDegrees)//初始(from)的角度,結束時(to)的角度
public RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,int pivotYType, float pivotYValue)

后面兩個構造方法的參數其實和上面介紹的Scale是一樣,就不做介紹了
XML配置文件

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:fromDegrees="0"
    android:pivotX="50%"
    android:pivotY="50%"
    android:toDegrees="360">
</rotate>

5.Animation中的interprolator

Animation中的interprolator最底層的接口是

public interface TimeInterpolator 

他的子類有:
AccelerateInterpolator 加速插值器(動畫速率開始很慢,然后逐漸加速)
DecelerateInterpolator 減速插值器(動畫速率開始很快,然后逐漸減速)
AccelerateDecelerateInterpolator 加速減速插值器(動畫速率開始慢然后塊)
LinearInterpolator 線性插值器(最簡單的插值器,即使動畫勻速運動)
BounceInterpolator 彈跳插值器(在動畫結束時使View呈彈跳狀態)
AnticipateInterpolator 回蕩秋千插值器(開始向后蕩,然后向前蕩的插值器)
CycleInterpolator 正弦周期變化插值器(動畫循環播放特定的次數,速率改變沿著正弦曲線)
OvershootInterpolator 向前甩一定值后再回到原來位置
AnticipateOvershootInterpolator 開始的時候向后然后向前甩一定值后返回最后的值

Property Animation

屬性動畫實在API3.0之后出現的。屬性動畫相對于Tween傳統動畫具有一定的優越性,因為傳統動畫是不斷調用onDraw()方法去重繪界面來實現動畫效果,這在一定程度上必定會加大CPU負擔,從而帶來性能問題,并且傳統動畫只是重繪了界面,改變了View的顯示位置,但是對用戶的onClick等響應事件并沒有發生相應的變化,所以傳統動畫并不適于那些具有交互的動畫效果。而屬性動畫是改變View的屬性值,真真正正改變了一個View,因此屬性動畫大大改變了傳統動畫的局限性。

ObjectAnimator

ObjectAnimator是屬性動畫中比較簡單基礎的類,我們可以使用以下方法為一個View添加動畫效果。

public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)

第一個參數即要添加動畫效果的View
第二個參數時屬性名稱。其實只要一個View的API中為某個屬性設置setter/getter方法,我們就可以為它添加屬性動畫,這個屬性名稱可以為"rotation"、"translateX"、"translateY"、"X"、"Y"等View屬性。
第三個參數是一個可變參數,即我們需要設置的動畫值。例如:

ObjectAnimator.ofFloat(img, "translateX", 0F, 100F);//X方向的偏移
ObjectAnimator.ofFloat(img, "translateY", 0F, 100F);//Y方向的偏移

多重動畫的添加,我們可以使用如下方式
方式一:

ObjectAnimator.ofFloat(img, "translateX", 0F, 100F).setDuration(1000).start();
ObjectAnimator.ofFloat(img, "translateY", 0F, 100F).setDuration(1000).start();

這種方式并不是先執行“translateX”動畫,再執行“translateY”動畫,而是同時執行
方式二:

PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("rotation",0F,360F);
PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("translateX",0F,100F);
ObjectAnimator.ofPropertyValuesHolder(img,p1,p2).setDuration(1000).start();

方式三:

Animator anim1 = ObjectAnimator.ofFloat(img, "translateX", 0F, 100F);
Animator anim2 = ObjectAnimator.ofFloat(img, "translateY", 0F, 100F);
AnimatorSet set = new AnimatorSet();
set.setDuration(1000);
set.playTogether(anim1,anim2);
set.start();

在AnimatorSet類中,有很多方法方便我們控制動畫的執行流程

public void playSequentially(Animator... items)//順序執行items
public Builder with(Animator anim)//與某個動畫同時執行
public Builder before(Animator anim)//在某個動畫執行之前執行anim
public Builder after(Animator anim)//在某個動畫執行后執行anim

動畫監聽事件AnimatorListener

ObjectAnimator anim = ObjectAnimator.ofFloat(root, "translateX", 0F, 100F);
anim.addListener(new Animator.AnimatorListener(){
    @Override
    public void onAnimationStart(Animator animation){}//動畫開始時執行
    @Override
    public void onAnimationEnd(Animator animation){}//動畫結束后執行
    @Override
    public void onAnimationCancel(Animator animation){}//動畫被取消掉時執行
    @Override
    public void onAnimationRepeat(Animator animation){}//動畫重復時執行
});

當然有時候我們并不需要監聽動畫的這么多事件,那么我們可以使用AnimatorListenerAdapter這個抽象類,去重寫我們需要監聽的事件即可。

anim1.addListener(new AnimatorListenerAdapter(){
    @Override
    public void onAnimationEnd(Animator animation){
        super.onAnimationEnd(animation);    
    }
});

Layout Animation

所謂布局動畫即添加到布局的動畫效果,并且動畫效果會影響到布局的子對象。
為布局添加動畫需要使用到LayoutAnimationController這個類,該類有兩個常用構造方法

public LayoutAnimationController(Animation animation)
public LayoutAnimationController(Animation animation, float delay)

這兩個構造比較容易理解,往構造方法中傳遞一個Animation參數即可。第二個構造方法中的delay(延遲)指子對象出現的先后延遲時間,即第一個View子對象開始出現后delay秒,第二個View子對象出現。
新建好LayoutAnimationController對象之后,使用

view.setLayoutAnimation(LayoutAnimationController controller)

這樣我們就為布局添加好了動畫效果。
LayoutAnimationController中有這樣一個方法setOrder(int order),該方法指定布局中子View出現的先后順序,API為我們制定了三個值,在LayoutAnimationController類中

ORDER_NORMAL//順序
ORDER_REVERSE//倒序
ORDER_RANDOM//隨機

為布局添加布局改變動畫
在Layout的XML配置文件中使用

android:animateLayoutChanges=["true"|"false"]

這樣就會為我們的布局添加一個系統默認的布局改變動畫效果。
當然我們也可以自定義這個動畫效果
使用view.setLayoutTransition(LayoutTransition transition)方法即為布局添加了一個默認的布局改變動畫,如果想改變這個動畫,需要使用到

public void setAnimator(int transitionType, Animator animator)

這個方法,第一個參數指布局改變的類型,在LayoutTransition 類中API為我們提供了5個值

CHANGE_APPEARING//由于主容器新增加了一個View,而導致原來的View位置發生改變時觸發的動畫
CHANGE_DISAPPEARING//由于主容器移除了一個View,而導致原來的View位置發生改變時觸發的動畫
APPEARING//View顯示時的動畫
DISAPPEARING//View消失時的動畫
CHANGING//包含上面所有的情況

XML配置文件
我們也可以在XML文件中為布局設置布局動畫
首先使用XML創建一個Tween Animation
然后使用XML通過以下語法創建一個布局動畫

<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
    android:animation="@[package:]anim/anim_resource_name"
    android:delay="0.5">
</layoutAnimation>

根節點必須是layoutAnimation,android:animation指定義的Tween Animation
最后在layout布局中為布局使用android:layoutAnimation="@[package:]anim/anim_resource_name"
將我們編寫的layoutAnimation文件的文件名傳遞進去即可。

Frame Animation

這種類型的動畫,在官方文檔中是這樣介紹的:

Frame動畫是一系列圖片按照一定的順序展示的過程,和放電影的機制很相似,我們稱之為逐幀動畫。Frame動畫既可以在XML文件中定義,也可以完全編碼實現。

XML配置文件
在XML中進行定義時,文件既可以放在anim目錄中也可以放在drawable文件中。語法如下:

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"  
    android:oneshot=["true" | "false"] >  
    <item  
        android:drawable="@[package:]drawable/drawable_resource_name"  
        android:duration="integer" />  
</animation-list>

animation-list作為根節點是必須的
android:oneshot若設值為true表示動畫執行一次,若設值為false表示動畫會重復執行。
每一個<item>元素表示一幀動畫,android:drawable表示一幀所對應的圖片,android:duration表示該幀所執行的時間。
Java Code
若以純編碼實現Frame動畫需要用到AnimationDrawable類,該類是Drawable的子類。
在Java代碼中我們可以使用setBackgroundResource()方法將我們XML中定義的Frame動畫設置到ImageView上

image.setBackgroundResource(R.anim.frame);  
AnimationDrawable anim = (AnimationDrawable) image.getBackground();  
anim.start();

如果想要停止掉動畫,只需調用anim.stop()方法即可。
還可以通過以下方式定義一個Frame動畫

AnimationDrawable frame = new AnimationDrawable();
for(int i = 0; i< 4; i++){
    int id = getResources().getIdentifier("f"+i,"drawable",getPackageName());
    Drawable drawable = getResources().getDrawable(id);
    frame.addFrame(drawable,300);
}
frame.setOneShot(true);
img.setBackgroundDrawable(frame);
frame.start();

注意:對于AnimationDrawable不要在Activity的onCreate()方法中去掉用start()方法,因為此時窗口對象Window還沒有初始化,AnimationDrawable不能被追加到Window中的視圖對象中,所以并沒有效果。解決辦法可以是將animation的start放在一個按鈕的點擊事件或其他響應事件中,也可以在onWindowFocusChanged方法中開始執行動畫,onWindowFocusChanged方法會在窗口初始化完成后被執行,在onCreate()方法之后執行。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容

  • 1 背景 不能只分析源碼呀,分析的同時也要整理歸納基礎知識,剛好有人微博私信讓全面說說Android的動畫,所以今...
    未聞椛洺閱讀 2,733評論 0 10
  • 轉載一篇高質量博文,原地址請戳這里轉載下來方便今后查看。1 背景不能只分析源碼呀,分析的同時也要整理歸納基礎知識,...
    Elder閱讀 1,951評論 0 24
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,677評論 25 708
  • 聽了別人的故事我還是挺羨慕我自己的 有些人并不是我們表面看上去那么光鮮亮麗 有些日子過的也并不是表面所看到的那樣的...
    囡嘜閱讀 227評論 0 0
  • 記得小時候,會呆呆地望著天上的星星,還記得有一個似勺子似的形狀的圖形,大人說叫北斗七星。看天上的月亮,好像里面有一...
    同處當下閱讀 147評論 2 0