Android中的动画
學(xué)習(xí)內(nèi)容
??幀動畫
??補間動畫
??動畫方式切換組件
能力目標(biāo)
??掌握Android中動畫的基本概念及分類
??熟練掌握幀動畫的實現(xiàn)
??熟練掌握各種補間動畫的實現(xiàn)
??掌握如何使用動畫方式實現(xiàn)組件之間的切換效果
本章簡介
在Android程序設(shè)計過程中,除了使用簡單的按鈕、文本框等簡單控件來構(gòu)建基本界面,我們還可以通過為界面添加動畫效果,使得界面更加變得更加絢麗,更加吸引人。Android平臺也提供了一套完整的動畫框架,使得開發(fā)者可以用它開發(fā)出各種動畫效果。
本章主要介紹Android系統(tǒng)中的動畫:幀動畫和補間動畫。其中幀動畫使用AnimationDrawable來實現(xiàn),在本質(zhì)上是將多個圖像以相同或不同的時間間隔進行切換來實現(xiàn)動畫。補間動畫需要指定動畫開始和結(jié)束狀態(tài),然后由系統(tǒng)自動生成中間狀態(tài)的圖像,它包括移動、縮放、旋轉(zhuǎn)、透明度的變化等。除此之外我們還將學(xué)習(xí)Android默認(rèn)提供的accelerate_interpolator、decelerate_interpolator、accelerate_decelerate_interpolator等多種動畫渲染器。
2.1?Android中的動畫
Android中的Animations動畫效果多種多樣,其中包括旋轉(zhuǎn)、縮放、淡入淡出等,這些效果可以應(yīng)用于絕大多數(shù)的控件(圖片、按鈕、文本)??偟膩碚f,默認(rèn)Android系統(tǒng)主要提供以下兩類動畫:
??幀動畫(Frame-By-Frame?Animations):通過順序播放事先做好的圖像來實現(xiàn)動畫效果,和電影相似。
??補間動畫(Tweened Animations):通過對場景里的對象不斷進行圖像變換(平移、縮放、旋轉(zhuǎn))來產(chǎn)生動畫效果。具體來講,Tween動畫是通過預(yù)先定義一組指令(這組指令指定了圖形變換類型、觸發(fā)時間、持續(xù)時間等),程序沿著時間軸執(zhí)行這些指令來實現(xiàn)動畫效果。
?
2.2?幀動畫
在Android系統(tǒng)中大多數(shù)免費應(yīng)用都會在界面中添加廣告以取得收入,而多數(shù)廣告都如我們經(jīng)??吹降?/span>GIF圖片那樣,幾張不同的圖片不斷變換以增加廣告內(nèi)容的充實度,而這里就需要我們使用幀動畫技術(shù)來實現(xiàn)這些效果。
幀動畫實際上是由若干個以一定的時間間隔進行切換的圖像組成的。比如電影的原理就類似于幀動畫,一般電影是每秒25幀。即,電影在每秒鐘之內(nèi)會以相等的時間間隔連續(xù)播放25幅靜態(tài)畫面,由于人的視覺暫留,在這樣的播放頻率下,看起來這些畫面好像是連續(xù)的。在第一章中我們在onDraw()方法中使用invalidate()方法不斷地刷新View的方式實現(xiàn)的旋轉(zhuǎn)動畫,這種情況下,是不斷地畫出動畫中的每一幀圖像,它其實也相當(dāng)于幀動畫。
要在Android中實現(xiàn)幀動畫,首先需要在res/anim目錄下創(chuàng)建一個后綴為.xml的動畫文件。然后在這個文件中指定動畫中的靜態(tài)圖像和每一張靜態(tài)圖像的停留時間,這個時間的單位是毫秒。為了讓用戶看起來舒服,一般可以將所有的圖像停留時間設(shè)為同一個值。動畫文件的一般形式如下。
<animation-list?android:oneshot="false"
xmlns:android="http://schemas.android.com/apk/res/android">?
<item?android:duration="500"?android:drawable="@drawable/a1"/>?
<item?android:duration="500"?android:drawable="@drawable/a2"/>?
……
</animation-list>
一般情況下,動畫文件由一個<animation-list>標(biāo)簽和若干個<item>標(biāo)簽組成。其中<animation-list>標(biāo)簽的android:oneshot屬性取值為true時表示動畫只運行一遍,為false時動畫會循環(huán)播放,這個屬性是可選的,默認(rèn)值是false。<item>標(biāo)簽的android:drawable屬性 ???用來指定動畫中靜態(tài)圖像資源的ID,android:duration用來指定每個圖像的停留時間,這兩個屬性都是必選的,缺一不可。
編寫完動畫文件之后,就需要裝載動畫文件,并創(chuàng)建AnimationDrawable對象。AnimationDrawable是Drawable的子類,它在Drawable的基礎(chǔ)之上提供了控制動畫的功能。
實現(xiàn)幀動畫的基本步驟是:
(1)?在drawable中插入一系列的圖片,注意這里面圖片的命名最好要有規(guī)律可循,以方便編程使用,例如我這里面的命名是a1、a2……。
(2)?在res/anim文件夾當(dāng)中創(chuàng)建一個xml類型的文件,將所有幀都列出來以定義Animations動畫序列,在此處可以通過oneshot設(shè)置動畫是否重復(fù)播放。
?
示例2.1:
實現(xiàn)GIF動畫的播放效果。
在屏幕上提供一個ImageView和四個Button,當(dāng)用戶單擊這些Button按鈕時,依次實現(xiàn)“開始動畫”、“停止動畫”、“運行一次動畫”、“代碼中添加動畫”的功能。其中ImageView組件的作用是按照我們在動畫文件中設(shè)置的順序顯示res/drawable目錄下的靜態(tài)圖片。整個程序運行的效果和GIF圖像基本一樣。整下程序的運行效果如下圖2.1.1和圖2.1.2所示:
?
?
?
?
(1)編寫動畫文件代碼如下:
<animation-list?android:oneshot="false"
xmlns:android="http://schemas.android.com/apk/res/android">?
?
<item?android:duration="500"?android:drawable="@drawable/a1"/>?
<item?android:duration="500"?android:drawable="@drawable/a2"/>?
<item?android:duration="500"?android:drawable="@drawable/a3"/>?
<item?android:duration="500"?android:drawable="@drawable/a4"/>?
<item?android:duration="500"?android:drawable="@drawable/a5"/>?
<item?android:duration="500"?android:drawable="@drawable/a6"/>?
<item?android:duration="500"?android:drawable="@drawable/a7"/>?
<item?android:duration="500"?android:drawable="@drawable/a8"/>
</animation-list>
(2)編寫程序布局文件,在布局文件中只是提供一個id為imageViewId的ImageView組件和四個id分別為btn1、btn2、btn3、btn4的Button組件。
(3)編寫Activity類,實現(xiàn)功能代碼如下:
public?class?FrameByFrameActivity extends?Activity {
private?ImageView imageView?=null;
private?AnimationDrawable drawable?= null;
????@Override
????public?void?onCreate(Bundle savedInstanceState) {
????????super.onCreate(savedInstanceState);
????????setContentView(R.layout.framebyframe);
????????
????????imageView?= (ImageView) findViewById(R.id.imageViewId);
????????
????????//開始動畫
????????Button btn = (Button) findViewById(R.id.btn1);
????????btn.setOnClickListener(new?View.OnClickListener() {
public?void?onClick(View v) {
//裝載動畫布局文件
imageView.setBackgroundResource(R.anim.framebyframe);
//構(gòu)建動畫
AnimationDrawable drawable = null;
drawable=(AnimationDrawable) imageView.getBackground();
//開始播放動畫
drawable.start();
}
});
????????//停止動畫
????????Button btn2 = (Button) findViewById(R.id.btn2);
????????btn2.setOnClickListener(new?View.OnClickListener() {
public?void?onClick(View v) {
drawable.stop();
}
});
????????
????????//運行一次動畫
????????Button btn3 = (Button) findViewById(R.id.btn3);
????????btn3.setOnClickListener(new?View.OnClickListener() {
public?void?onClick(View v) {
drawable.setOneShot(true);
drawable.start();
}
});
????????//添加動畫
????????Button btn4 = (Button) findViewById(R.id.btn4);
????????btn4.setOnClickListener(new?View.OnClickListener() {
public?void?onClick(View v) {
//裝載動畫布局文件
?
//AnimationDrawable對象用來表示Frame動畫
AnimationDrawable frameDrable = new?AnimationDrawable();
Drawable drawable = null;
//裝載資源
for(int?i = 1 ; i <10 ;i++){
int?id = getResources().getIdentifier("a"+i, "drawable", getPackageName());
drawable = getResources().getDrawable(id);
frameDrable.addFrame(drawable, 1000);//把每一幀要顯示的內(nèi)容添加進去
}
//設(shè)置動畫不重復(fù)播放
frameDrable.setOneShot(false);
imageView.setBackgroundDrawable(frameDrable);
//開始播放動畫
frameDrable.start();
}
});
????????
????}
}
?
在btn1按鈕的單擊事件中,我們實現(xiàn)了動畫文件的裝載、AnimationDrawable的構(gòu)建及動畫的播放功能。
除了示例代碼中使用ImageView的setBackgroundResource()方法來裝載動畫文件,并通過ImageView的getBackground()方法獲得AnimationDrawable對象實現(xiàn)動畫效果之外,我們還可以使用getDrawable()方法來裝載動畫文件,代碼如下:
AnimationDrawable drawable =
(AnimationDrawable) getResources().getDrawable(R.anim.framebyframe);
imageView.setBackgroundDrawable(drawable);
在btn4按鈕的單擊事件中,我們先通過new關(guān)鍵字聲明了一個AnimationDrawable對象,然后利用Java代碼通過循環(huán)的方式為這個對象添加了一系列的靜態(tài)圖片。最后調(diào)用start()方法讓其運動起來。
通過上述代碼我們會發(fā)現(xiàn),所有對幀動畫的控制都是通過AnimationDrawable實現(xiàn)的。本示例程序中用到的AnimationDrawable中與幀動畫有關(guān)的方法如下:
??start():開始播放動畫
??stop():停止播放動畫
??void setOneShot(boolean ?b):
設(shè)置是否只播放一遍幀動畫。這個方法的參數(shù)與動畫文件中的<animation-list>標(biāo)簽的android:oneshot屬性值的含義相同。
??void ?addFrame(Drawable?frame, int duration)
向AnimationDrawable對象中添加新的幀。其中參數(shù)frame是一個Drawable對象,表示要添加的幀,該參數(shù)可以是靜態(tài)圖像,也可以是另一個動畫。參數(shù)duration表示幀動畫的停留時間,如果新添加的幀是動畫,那么這停留時間就是新添加的動畫可以播放的時間,如果到了停止時間,不管新添加的動畫是否播放完,都會切換到下一個靜態(tài)圖像或動畫。
2.3?補間動畫
通過上述的幀動畫(Frame-By-Frame?Animations)技術(shù),我們可以方便的制作出如flash般的動畫效果,只需要我們準(zhǔn)備好每一幀動畫所需要的畫面,然后按照組織好的順序使其順序播放,即可達(dá)到動畫片似的效果,但是,如果僅僅是一個物體的簡單移動,放大縮小等功能,我們依然需要為其準(zhǔn)備不同時刻的靜態(tài)畫面,按照電影一秒內(nèi)播放25幀的速度,四秒時長的動畫效果我們就需要為其準(zhǔn)備多達(dá)100張靜態(tài)圖片,這樣看來依然過于繁瑣,而對于這種簡單的移動、放大縮小、旋轉(zhuǎn)等動畫效果,安卓系統(tǒng)也為我們提供了更加方便的動畫生成技術(shù),我們稱之為補間動畫(Tweened Animations)。
補間動畫(Tweened Animations)是指在制作動畫過程中,開發(fā)者只用定義動畫的開始、結(jié)束等等關(guān)鍵幀信息,中間的變化效果由系統(tǒng)自動生成,所以稱之為補間動畫。
對于圖像的簡單移動、旋轉(zhuǎn)、縮放等,都可以通過補間動畫來實現(xiàn)。然而,當(dāng)圖像過于復(fù)雜時,由于系統(tǒng)無法預(yù)料下一幅畫面的樣子,此時不宜采用補間動畫,要實現(xiàn)動畫效果只能采用幀動畫的形式。
因為補間動畫只需要提供兩幀圖像(第一幀和最后一幀),并指定動畫的持續(xù)時間即可。所以補間動畫最大的優(yōu)點是節(jié)省硬盤空間。
Android中使用Animation類代表抽象的動畫類,它包含以下幾個子類:
??TranslateAnimation:位移變化的動畫,創(chuàng)建該動畫時只要指定動畫開始時的位置(以X、Y坐標(biāo)來表示)、結(jié)束時的位置(以X、Y坐標(biāo)來表示),并指定動畫持續(xù)的時間即可。
??RotateAnimation:旋轉(zhuǎn)動畫,創(chuàng)建該動畫時只要指定動畫開始時的旋轉(zhuǎn)角度、結(jié)束時的旋轉(zhuǎn)角度,并指定動畫持續(xù)的時間即可。由于旋轉(zhuǎn)時以不同點為中心時旋轉(zhuǎn)效果并不相同,因此指定旋轉(zhuǎn)動畫時還要指定“旋轉(zhuǎn)中心”的坐標(biāo)。
??ScaleAnimation:縮放動畫,創(chuàng)建該動畫時要指定動畫開始時的縮放比(以X、Y軸的縮放參數(shù)表示)、結(jié)束時動畫的縮放比以X、Y軸的縮放參數(shù)表示),并指定動畫持續(xù)的時間。由于旋轉(zhuǎn)時以不同點為中心時縮放效果并不相同,因此指定縮放動畫時還要指定“縮放中心”的坐標(biāo)。
??AlphaAnimation:透明度改變動畫,創(chuàng)建該動畫時需要指定動畫開始時的透明度、結(jié)束時的透明度和動畫持續(xù)時間,其中透明度的變化范圍是1~0。
在本節(jié)中我們將通過具體的案例深入學(xué)習(xí)Android系統(tǒng)默認(rèn)提供的移動、縮放、旋轉(zhuǎn)和透明四種補間動畫效果。
2.3.1?移動補間動畫
《水果忍者》也許很多同學(xué)都玩過,游戲中玩家需要用手指模擬武士刀將上拋起的各種水果切開,那么這種水果上下移動的動畫效果如何實現(xiàn)呢?這里我們就可以使用移動補間動畫來實現(xiàn)。
移動是最常見的動畫效果,可以通過配置文件或Java代碼文件來實現(xiàn)。
示例2.2
上下跳動的小球。
在手機屏幕上顯示一下上下移動的小球,用來模擬物體的自由下落:當(dāng)小球從上到下移動時呈現(xiàn)加速狀態(tài),從下到上移動時呈現(xiàn)減速狀態(tài)。
補間動畫文件放在res/anim目錄中,在動畫文件中通過<translate>標(biāo)簽設(shè)置移動的效果。本示例用到兩個動畫渲染器:accelerate_interpolator、decelerate_interpolator。首先定義具體動畫的文件。
translatescaletop.xml定義從下到上移動,減速效果。
<?xml?version="1.0"?encoding="utf-8"?>
<translate?xmlns:android="http://schemas.android.com/apk/res/android"
????android:interpolator="@android:anim/accelerate_interpolator"
????android:fromXDelta="0"
????android:toXDelta="0"
????android:fromYDelta="250"
????android:toYDelta="0"
????android:duration="2200"?/>
translatebottom.xml定義從上到下移動,加速效果。
<?xml?version="1.0"?encoding="utf-8"?>
<translate?xmlns:android="http://schemas.android.com/apk/res/android"
????android:interpolator="@android:anim/?decelerate_interpolator"
????android:fromXDelta="0"
????android:toXDelta="0"
????android:fromYDelta="0"
????android:toYDelta="250"
android:duration="2200"?/>
<translate>標(biāo)簽中設(shè)置了幾個屬性,這些屬性的含義如下:
??android:interpolator:表示動畫渲染器, Android系統(tǒng)一共為我們提供了linear_interpolator、accelerate_interpolator(動畫加速器)、decelerate_interpolator(動畫減速器)和accelerate_decelerate_interpolator(動畫加速減速器)四種動畫渲染器,其中動畫加速減速器使動畫在開始和結(jié)束時速度很慢,但在前半部分開始加速,后半部分開始減速。
??android:fromXDelta:動畫起始位置的橫坐標(biāo)。
??android:toXDelta:動畫結(jié)束位置的橫坐標(biāo)。
??android:fromYDelta:動畫起始位置的縱坐標(biāo)。
??android:toYDelta:動畫結(jié)束位置的縱坐標(biāo)。
??android:duration:動畫持續(xù)的時間。
Activity類代碼如下:
public?class?BallAnimationsActivity extends?Activity implements?AnimationListener {
private?ImageView imageView?= null;
private?Animation animationBottom;//從上到下
private?Animation animationTop;//從下到上
?
@Override
protected?void?onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.ballanimations);
?
imageView?= (ImageView) findViewById(R.id.imageview);
Button button = (Button) findViewById(R.id.button);
?
button.setOnClickListener(new?OnClickListener() {
@Override
public?void?onClick(View v) {
imageView.startAnimation(animationBottom);
}
});
?
animationBottom?= AnimationUtils.loadAnimation(this, R.anim.transloatebottom);
animationTop?= AnimationUtils.loadAnimation(this, R.anim.transloatetop);
animationBottom.setAnimationListener(this);
animationTop.setAnimationListener(this);
}
?
@Override
public?void?onAnimationStart(Animation animation) {
//動畫開始時調(diào)用
}
?
@Override
public?void?onAnimationEnd(Animation animation) {//動畫結(jié)束時調(diào)用
//根據(jù)當(dāng)前顯示的動畫決定下次顯示哪一個動畫
if?(animation.hashCode() == animationBottom.hashCode())
imageView.startAnimation(animationTop);
else?if?(animation.hashCode() == animationTop.hashCode())
imageView.startAnimation(animationBottom);
}
?
@Override
public?void?onAnimationRepeat(Animation animation) {//動畫循環(huán)時調(diào)用
?
}
}
代碼解析:
其中ballanmimations.xml是一個只提供了一個包含id為imageView的ImageView組件和一個id為btn的Button組件的布局文件。
補間動畫有動畫開始、動畫結(jié)束、動畫循環(huán)3種狀態(tài):,我們可以通過android.view.animation.Animation.AnimationListener接口實現(xiàn)對這三種狀態(tài)的監(jiān)聽。這個接口中定義的三個方法:onAnimationStart()、onAnimationEnd()、onAnimationRepeat()分別在動畫開始、動畫結(jié)束和動畫循環(huán)時被調(diào)用。
將動畫文件應(yīng)用到指定的組件上,除了可以使用示例中調(diào)用startAnimation()方法外,還可以使用如下方法:
imageView.setAnimation(animationBottom);
animation.start();
程序中裝載動畫文件時用到了如下方法:
Animation??AnimationUtils.loadAnimation(Context?context, int id)
從資源文件中裝載動畫。其中id表示動畫文件的資源ID。
單擊【開始動畫】按鈕后,小球就會在垂直方向上按照我們的設(shè)置上下移動,效果如下圖2.1.3所示。
?
2.3.2?縮放補間動畫
在《憤怒的小鳥》的游戲中,當(dāng)我們需要讓小鳥由遠(yuǎn)及近或者由近及遠(yuǎn)飛翔時,那么它應(yīng)該是出現(xiàn)一種由小變大或者由大變小的狀態(tài)來模擬距離的改變,而這種動畫的實現(xiàn),我們就需要用到下面的縮放補間動畫技術(shù)。
示例2.3:
實現(xiàn)一個可以跳動的心.跳動實際上就是不斷地將心型的圖像放大和縮小,因此本示例需要兩個動畫文件,一個表示放大后的狀態(tài),一個表示縮小后的狀態(tài)。
心臟放大的配置文件scalelarge.xml代碼如下:
<scale?xmlns:android="http://schemas.android.com/apk/res/android"
????android:duration="500"
????android:fromXScale="0.2"
????android:toXScale="1.0"
????android:fromYScale="0.2"
????android:toYScale="1.0"?
????android:interpolator="@android:anim/decelerate_interpolator"
????android:pivotX="50%"
????android:pivotY="50%"?/>
心臟縮小的配置文件scalesmall.xml代碼如下:
<scale?xmlns:android="http://schemas.android.com/apk/res/android"
????android:duration="500"
????android:fromXScale="1.0"
????android:fromYScale="1.0"
????android:interpolator="@android:anim/accelerate_interpolator"
????android:pivotX="50%"
????android:pivotY="50%"
????android:toXScale="0.2"
android:toYScale="0.2"?/>
<scale>標(biāo)簽中設(shè)置了幾個屬性,這些屬性的含義如下:
??android:fromXScale:表示沿X軸縮放的起始比例。
??android:toXScale:表示沿X軸縮放的結(jié)束比例。
??android:fromYScale:表示沿Y軸縮放的起始比例。
??android:toYScale:表示沿Y軸縮放的結(jié)束比例。
??android:pivotX:表示沿X軸方向上縮放的中心點位置。
??android:pivotY:表示沿Y軸方向上縮放的中心點位置。
接下來在Activity中編寫功能實現(xiàn)代碼。
public?class?HeartScaleActivity extends?Activity implements?AnimationListener {
private?Animation large;
private?Animation small;
private?ImageView imageView;
?
@Override
public?void?onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.heartanimations);
imageView?= (ImageView) findViewById(R.id.imageview);
large?= AnimationUtils.loadAnimation(this, R.anim.scalelarge);
small?= AnimationUtils.loadAnimation(this, R.anim.scalesmall);
large.setAnimationListener(this);
small.setAnimationListener(this);
imageView.startAnimation(small);
}
@Override
public?void?onAnimationEnd(Animation animation) {
if?(animation.hashCode() == large.hashCode())
imageView.startAnimation(small);
else
imageView.startAnimation(large);
?
}
?
@Override
public?void?onAnimationRepeat(Animation animation) {
}
?
@Override
public?void?onAnimationStart(Animation animation) {
}
}
其中heartanmimations.xml是一個只提供了一個包含id為imageView的ImageView布局文件。
任意選取兩個時刻,程序運行效果如下圖2.1.4和圖2.1.5所示。
?
圖2.1.4 心形放大的圖像
?
圖2.1.5 心型縮小圖像
2.3.3?旋轉(zhuǎn)補間動畫
在游戲中,很多時候我們要實現(xiàn)某個物品按照某個點不斷旋轉(zhuǎn)的效果,例如《瘋狂的小鳥》游戲中,當(dāng)小鳥撞上障礙物時,就會不斷旋轉(zhuǎn)著跌落下去,這里小鳥的運動顯然除了旋轉(zhuǎn),還有一個自由落體的運動過程,而單就旋轉(zhuǎn)這種簡單的動畫來說,我們就可以運用Android系統(tǒng)中提供的旋轉(zhuǎn)補間動畫來實現(xiàn)。
示例2.4:模擬實現(xiàn)月球環(huán)繞地球旋轉(zhuǎn)的效果,如下圖2.1.6所示。
?
圖2.1.6 地月系
定義地球自轉(zhuǎn)動畫的xml文件earth.xml內(nèi)容如下:
<rotate?xmlns:android="http://schemas.android.com/apk/res/android"
????android:duration="20000"
????android:fromDegrees="0"
????android:pivotX="50%"
????android:pivotY="50%"
android:repeatCount="infinite"
android:repeatMode="restart"
????android:toDegrees="360"?/>
定義月球圍繞地球旋轉(zhuǎn)動畫的xml文件moon.xml內(nèi)容如下:
<rotate?xmlns:android="http://schemas.android.com/apk/res/android"
????android:duration="10000"
????android:fromDegrees="0"
????android:pivotX="200%"
????android:pivotY="300%"
????android:repeatCount="infinite"
????android:repeatMode="restart"
????android:toDegrees="360"?/>
<rotate>標(biāo)簽中設(shè)置了幾個屬性,這些屬性的含義如下:
??android: fromDegrees:表示旋轉(zhuǎn)的起始角度。
??android:toDegrees:表示旋轉(zhuǎn)的結(jié)束角度。
??android:repeatCount:用來設(shè)置旋轉(zhuǎn)的次數(shù)。當(dāng)取值為0時(默認(rèn)),從0度旋轉(zhuǎn)到360度,動畫就會停止;如果屬性值為N(N>0),動畫會不停地顯示N+1次;當(dāng)取值為infinite或-1時,動畫會永不停地運行下去。
??android:repeatMode:用來設(shè)置旋轉(zhuǎn)的模式。默認(rèn)值是restart,該屬性值只有當(dāng)android:repeatCount設(shè)置成大于0的數(shù)或infinite時才起作用。該屬性取值reverse時表示偶數(shù)次顯示動畫時會做與動畫文件定義的方向相反的動作。
??pivotX:旋轉(zhuǎn)支點橫坐標(biāo)。
??pivotY:旋轉(zhuǎn)支點縱坐標(biāo)。
pivotX和pivotY的取值有兩種:float或百分?jǐn)?shù),分別是相對于物體左(上)邊距的像素表示或相對于物體左(上)邊距的百分?jǐn)?shù)表示。旋轉(zhuǎn)支點坐標(biāo)的具體計算公式如下:
假如物體原來的坐標(biāo)是(x0,y0),采用像素形式時pivotX=x1,pivotY=y1,采用百分比形式時pivotX=n1%,pivotY=n2%。那么最終旋轉(zhuǎn)中心的坐標(biāo)為(x0+x1,y0+y1)或(x0+width*n1%,y0+height*n2%),其中width和height分別指圖片的寬度和高度。
?
Activity類代碼:
public?class?EarthMoonActivity extends?Activity {
@Override
public?void?onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.earthmoon);
ImageView moon = (ImageView) findViewById(R.id.moon);
ImageView earth = (ImageView) findViewById(R.id.earth);
Animation moonAnimation = AnimationUtils.loadAnimation(this, R.anim.moon);
Animation earthAnimation = AnimationUtils.loadAnimation(this, R.anim.earth);
moon.startAnimation(moonAnimation);
earth.startAnimation(earthAnimation);
}
}
其中布局文件earthmoon.xml采用絕對布局,在其中放置了兩個id分別為moon和earth的ImageView組件,詳細(xì)代碼如下:
<?xml?version="1.0"?encoding="utf-8"?>
<AbsoluteLayout?xmlns:android="http://schemas.android.com/apk/res/android"
????android:layout_width="fill_parent"
????android:layout_height="fill_parent"
????android:gravity="center_vertical"
????android:orientation="vertical"?>
????<ImageView
????????android:id="@+id/moon"
????????android:layout_width="50dp"
????????android:layout_height="50dp"
????????android:layout_x="50dp"
????????android:layout_y="50dp"
????????android:src="@drawable/moon"?/>
????<ImageView
????????android:id="@+id/earth"
????????android:layout_width="80dp"
????????android:layout_height="80dp"
????????android:layout_x="120dp"
????????android:layout_y="200dp"
????????android:src="@drawable/ball" />
</AbsoluteLayout>
運行程序,會發(fā)現(xiàn)代表月亮的圖片會按照逆時針方向圍繞著地球旋轉(zhuǎn),而地球本身也會按照順時針的方向圍繞著自身的地軸旋轉(zhuǎn)。
2.3.4?透明補間動畫
很多游戲在設(shè)計時,都會讓已經(jīng)被消滅的敵人慢慢地在屏幕中變成透明狀,最后完全消失,以避免擠占寶貴的屏幕顯示資源,而在Android系統(tǒng)中,這種效果同樣十分簡單,只需要運用我們下面提到的這種技術(shù)即可——透明補間動畫。
示例2.5:
通過改變圖片透明度實現(xiàn)屏幕上對象逐漸消失的效果。
動畫效果定義文件alpha.xml內(nèi)容如下:
<?xml?version="1.0"?encoding="utf-8"?>
<set?xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_interpolator"
android:shareInterpolator?=?"true">
<alpha
android:fromAlpha="1.0"
android:toAlpha?=?"0.0"
android:startOffset=?"200"
android:duration?=?"3000"
/>
</set>
這個文件定義中各個屬性含義如下:
??android:fromAlpha:表示起始透明度,取值在0.0~1.0之間,其中0.0表示完全透明,1.0表示完全不透明。
??android:toAlpha:表示結(jié)束透明度。
??android:shareInterpolator = "true":設(shè)置內(nèi)部所有的控件共享Interpolator。
??android:startOffset:開始時間偏移量,指在動畫開始前等待的時間。
布局文件代碼:
<?xml?version="1.0"?encoding="utf-8"?>
<AbsoluteLayout?xmlns:android="http://schemas.android.com/apk/res/android"
????android:layout_width="fill_parent"
????android:layout_height="fill_parent"
????android:gravity="center_vertical"
????android:orientation="vertical"?>
????<ImageView
????????android:id="@+id/earth"
????????android:layout_width="80dp"
????????android:layout_height="80dp"
????????android:layout_x="120dp"
????????android:layout_y="100dp"
????????android:src="@drawable/ball"?/>
</AbsoluteLayout>
Activity類代碼:
public?class?EarthMoonActivity extends?Activity {
@Override
public?void?onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.earthmoon);
ImageView earth = (ImageView) findViewById(R.id.earth);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.alpha);
earth.startAnimation(animation);
}
}
?
某一時刻程序的運行效果如下圖2.1.7所示:
?
圖2.1.7 透明效果
2.4?動畫方式切換各組件
最后讓我們將上述提到的幾種技術(shù)融合在一起,運用到我們的Android組件中,為Android系統(tǒng)組件的切換提供絢麗的動畫效果。
凡是使用過Android手機的用戶,都一定會被它里面的程序組件之間的切換效果所吸引,比如Android系統(tǒng)自帶的看圖軟件在各圖片之間切換時的過渡效果。本節(jié)課中我們就借助android.widget.ViewFliper類來模擬實現(xiàn)這種過渡效果。
示例2.6:
實現(xiàn)Android中查看圖片時的過渡效果。
具體效果如下圖2.1.8和2.1.9所示,第一種效果是移動切換,第二種效果是淡入淡出切換。
?
圖2.1.8 水平移動切換
?
?
圖2.1.9 淡入淡出切換
本示例程序使用布局文件layout1.xml、layout2.xml、layout3.xml定義了3個View,每一個View中都包含一個用來顯示圖像的ImageView組件。當(dāng)用戶觸摸第一個圖像時,會以水平向左移動的方式切換到第二個圖像,觸摸第二個圖像時會以淡入淡出的方式切換到第三個圖像(通過透明度補間動畫實現(xiàn))。
水平移動向左切入的動畫文件translatein.xml的內(nèi)容如下:
<translate?xmlns:android="http://schemas.android.com/apk/res/android"
????android:duration="3000"
????android:fromXDelta="320"
????android:fromYDelta="0"
????android:interpolator="@anim/linear_interpolator"
????android:toXDelta="0"
????android:toYDelta="0"?/>
水平移動向左切出的動畫文件translateout.xml內(nèi)容如下:
<translate?xmlns:android="http://schemas.android.com/apk/res/android"
????android:duration="3000"
????android:fromXDelta="0"
????android:fromYDelta="0"
????android:interpolator="@anim/linear_interpolator"
????android:toXDelta="-320"
????android:toYDelta="0"?/>
淡入淡出動畫的淡入效果文件alphain.xml的內(nèi)容如下:
<alpha?xmlns:android="http://schemas.android.com/apk/res/android"
????android:duration="2000"
????android:fromAlpha="0"
????android:interpolator="@android:anim/accelerate_interpolator"
????android:toAlpha="1"?/>
淡入淡出動畫的淡出效果文件alphaout.xml的內(nèi)容如下:
<alpha?xmlns:android="http://schemas.android.com/apk/res/android"
????android:duration="2000"
????android:fromAlpha="1"
????android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0"?/>
Activity類代碼如下:
public?class?ViewFlipperActivity extends?Activity implements?OnTouchListener {
private?ViewFlipper viewFlipper;
private?Animation translateIn;
private?Animation translateOut;
private?Animation alphaIn;
private?Animation alphaOut;
?
@Override
public?boolean?onTouch(View view, MotionEvent event) {
switch?(view.getId()) {
case?R.id.imageview1://觸摸第一個圖像時:移動補間動畫
viewFlipper.setInAnimation(translateIn);
viewFlipper.setOutAnimation(translateOut);
break;
case?R.id.imageview2://觸摸第二個圖像時:透明漸變補間動畫
viewFlipper.setInAnimation(alphaIn);
viewFlipper.setOutAnimation(alphaOut);
break;
}
?
viewFlipper.showNext();//顯示下一個View
?
return?false;
}
?
@Override
public?void?onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewFlipper?= (ViewFlipper) getLayoutInflater().inflate(R.layout.viewflipper, null);
View view1 = getLayoutInflater().inflate(R.layout.layout1, null);
View view2 = getLayoutInflater().inflate(R.layout.layout2, null);
View view3 = getLayoutInflater().inflate(R.layout.layout3, null);
viewFlipper.addView(view1);
viewFlipper.addView(view2);
viewFlipper.addView(view3);
setContentView(viewFlipper);
translateIn?= AnimationUtils.loadAnimation(this, R.anim.translatein);
translateOut?= AnimationUtils.loadAnimation(this, R.anim.translateout);
alphaIn?= AnimationUtils.loadAnimation(this, R.anim.alphain);
alphaOut?= AnimationUtils.loadAnimation(this, R.anim.alphaout);
ImageView imageView1 = (ImageView) view1.findViewById(R.id.imageview1);
ImageView imageView2 = (ImageView) view2.findViewById(R.id.imageview2);
imageView1.setOnTouchListener(this);
imageView2.setOnTouchListener(this);
?
}
}
其中布局文件viewflipper.xml的代碼如下:
<ViewFlipper?xmlns:android="http://schemas.android.com/apk/res/android"
????android:layout_width="fill_parent"
????android:layout_height="fill_parent"?>
</ViewFlipper>
運行本程序,觸摸第一幅圖像會以水平移動的方式切換到第二幅圖像,再次觸摸第二幅圖像會以淡入淡出的方式切換到第三幅圖像。具體程序運行效果請參看圖2.1.8和圖2.1.9。
?
?
?
?
任務(wù)實訓(xùn)部分?
?
1:利用幀動畫技術(shù)開發(fā)一個游戲人物走動的小游戲
訓(xùn)練技能點
幀動畫的實現(xiàn)原理及技巧
需求說明
在任何一款游戲中,都不可避免地出現(xiàn)人物等對象走動的情景,結(jié)合本章所學(xué)的知識,我們可以事先提供一系列的圖片,然后利用幀動畫的原理實現(xiàn)。
實現(xiàn)步驟
具體的實現(xiàn)步驟請參看課本2.2節(jié)中的內(nèi)容。本案例的難點是準(zhǔn)備合適的人物行走過程中的圖像,然后在動畫文件中進行合適的設(shè)置。
?
?
2:?模擬實現(xiàn)汽車由近到遠(yuǎn)逐漸消失的場景
訓(xùn)練技能點
??移動補間動畫
??縮放補間動畫
??透明補間動畫
需求說明
在我們的手機程序中會經(jīng)常看到一個物體由遠(yuǎn)到近或由近到遠(yuǎn)、體積由大到小或由小到大、逐漸透明或逐漸消失的應(yīng)用。比如極品飛車游戲中漸行漸遠(yuǎn)的汽車。
本實訓(xùn)中要求模擬實現(xiàn)汽車由近到遠(yuǎn)逐漸消失的過程。汽車由近到遠(yuǎn)可通過移動補間動畫實現(xiàn);在消失過程中體積變小的過程可以通過縮放補間動畫實現(xiàn);為了增加用戶的觀感,可以在汽車消失的過程中為汽車設(shè)置一個透明度逐漸變化的過程,這個可通過透明補間動畫實現(xiàn)。
?
鞏固練習(xí)
一、簡答題
1.?簡述實現(xiàn)幀動畫的基本步驟。
?
?
2.?簡要描述Android默認(rèn)提供的四類補間動畫。
?
?
二、上機練習(xí)
完成一個蝴蝶振動翅膀飛動的效果,蝴蝶的振翅效果可通過逐幀動畫實現(xiàn),飛行時位置的改變可通過補間動畫實現(xiàn)。
總結(jié)
以上是生活随笔為你收集整理的Android中的动画的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android 十八 蓝牙及Wi-Fi
- 下一篇: OpenGL ES