本文實例分析了Android動畫之逐幀動畫。分享給大家供大家參考,具體如下:
在開始實例講解之前,先引用官方文檔中的一段話:
Frame動畫是一系列圖片按照一定的順序展示的過程,和放電影的機制很相似,我們稱爲逐幀動畫。Frame動畫可以被定義在XML文件中,也可以完全編碼實現。
如果被定義在XML文件中,我們可以放置在/res下的anim或drawable目錄中(/res/[anim | drawable]/filename.xml),文件名可以作爲資源ID在代碼中引用;如果由完全由編碼實現,我們需要使用到AnimationDrawable對象。
如果是將動畫定義在XML文件中的話,語法如下:
1
2
3
4
5
6
7
|
<? xml
version = "1.0"
encoding = "utf-8" ?>
android:oneshot=["true"
| "false"] >
< item
android:drawable = "@[package:]drawable/drawable_resource_name"
android:duration = "integer"
/>
</ animation-list >
|
需要注意的是:
<animation-list>元素是必須的,並且必須要作爲根元素,可以包含一或多個<item>元素;android:onshot如果定義爲true的話,此動畫只會執行一次,如果爲false則一直循環。
<item>元素代表一幀動畫,android:drawable指定此幀動畫所對應的圖片資源,android:druation代表此幀持續的時間,整數,單位爲毫秒。
文檔接下來的示例我就不在解說了,因爲接下來我們也要結合自己的實例演示一下這個過程。
我們新建一個名爲anim的工程,將四張連續的圖片分別命名爲f1.png,f2.png,f3.png,f4.png,放於drawable目錄,然後新建一個frame.xml文件:
1
2
3
4
5
6
7
8
|
<? xml
version = "1.0"
encoding = "utf-8" ?>
android:oneshot = "false" >
< item
android:drawable = "@drawable/f1"
android:duration = "300"
/>
< item
android:drawable = "@drawable/f2"
android:duration = "300"
/>
< item
android:drawable = "@drawable/f3"
android:duration = "300"
/>
< item
android:drawable = "@drawable/f4"
android:duration = "300"
/>
</ animation-list >
|
我們可以將frame.xml文件放置於drawable或anim目錄,官方文檔上是放到了drawable中了,大家可以根據喜好來放置,放在這兩個目錄都是可以運行的。
然後介紹一下佈局文件res/layout/frame.xml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
<? xml
version = "1.0"
encoding = "utf-8" ?>
< LinearLayout
android:orientation = "vertical"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent" >
< ImageView
android:id = "@+id/frame_image"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"
android:layout_weight = "1" />
< Button
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:text = "stopFrame"
android:onClick = "stopFrame" />
< Button
android:layout_width = "fill_parent"
android:layout_height = "wrap_content"
android:text = "runFrame"
android:onClick = "runFrame" />
</ LinearLayout >
|
我們定義了一個ImageView作爲動畫的載體,然後定義了兩個按鈕,分別是停止和啓動動畫。
接下來介紹一下如何通過加載動畫定義文件來實現動畫的效果。我們首先會這樣寫:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package
com.scott.anim;
import
android.app.Activity;
import
android.graphics.drawable.AnimationDrawable;
import
android.graphics.drawable.Drawable;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.ImageView;
public
class
FrameActivity extends
Activity {
private
ImageView image;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.frame);
image
= (ImageView) findViewById(R.id.frame_image);
image.setBackgroundResource(R.anim.frame);
AnimationDrawable
anim = (AnimationDrawable) image.getBackground();
anim.start();
}
}
|
看似十分完美,跟官方文檔上寫的一樣,然而當我們運行這個程序時會發現,它只停留在第一幀,並沒有出現我們期望的動畫,也許你會失望的說一句:“Why?”,然後你把相應的代碼放在一個按鈕的點擊事件中,動畫就順利執行了,再移回到onCreate中,還是沒效果,這個時候估計你會氣急敗壞的吼一句:“What the fuck!”。但是,什麼原因呢?如何解決呢?
出現這種現象是因爲當我們在onCreate中調用AnimationDrawable的start方法時,窗口Window對象還沒有完全初始化,AnimationDrawable不能完全追加到窗口Window對象中,那麼該怎麼辦呢?我們需要把這段代碼放在onWindowFocusChanged方法中,當Activity展示給用戶時,onWindowFocusChanged方法就會被調用,我們正是在這個時候實現我們的動畫效果。當然,onWindowFocusChanged是在onCreate之後被調用的,如圖:
然後我們需要重寫一下代碼:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
package
com.scott.anim;
import
android.app.Activity;
import
android.graphics.drawable.AnimationDrawable;
import
android.graphics.drawable.Drawable;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.ImageView;
public
class
FrameActivity extends
Activity {
private
ImageView image;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.frame);
image
= (ImageView) findViewById(R.id.frame_image);
}
@Override
public
void
onWindowFocusChanged( boolean
hasFocus) {
super .onWindowFocusChanged(hasFocus);
image.setBackgroundResource(R.anim.frame);
AnimationDrawable
anim = (AnimationDrawable) image.getBackground();
anim.start();
}
}
|
運行一下,動畫就可以正常顯示了。
如果在有些場合,我們需要用純代碼方式實現一個動畫,我們可以這樣寫:
1
2
3
4
5
6
7
8
9
|
AnimationDrawable
anim = new
AnimationDrawable();
for
( int
i = 1 ;
i <= 4 ;
i++) {
int
id = getResources().getIdentifier( "f"
+ i, "drawable" ,
getPackageName());
Drawable
drawable = getResources().getDrawable(id);
anim.addFrame(drawable,
300 );
}
anim.setOneShot( false );
image.setBackgroundDrawable(anim);
anim.start();
|
完整的FrameActivity.java代碼如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
package
com.scott.anim;
import
android.app.Activity;
import
android.graphics.drawable.AnimationDrawable;
import
android.graphics.drawable.Drawable;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.ImageView;
public
class
FrameActivity extends
Activity {
private
ImageView image;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.frame);
image
= (ImageView) findViewById(R.id.frame_image);
}
@Override
public
void
onWindowFocusChanged( boolean
hasFocus) {
super .onWindowFocusChanged(hasFocus);
image.setBackgroundResource(R.anim.frame);
AnimationDrawable
anim = (AnimationDrawable) image.getBackground();
anim.start();
}
public
void
stopFrame(View view) {
AnimationDrawable
anim = (AnimationDrawable) image.getBackground();
if
(anim.isRunning()) {
anim.stop();
}
}
public
void
runFrame(View view) {
AnimationDrawable
anim = new
AnimationDrawable();
for
( int
i = 1 ;
i <= 4 ;
i++) {
int
id = getResources().getIdentifier( "f"
+ i, "drawable" ,
getPackageName());
Drawable
drawable = getResources().getDrawable(id);
anim.addFrame(drawable,
300 );
}
anim.setOneShot( false );
image.setBackgroundDrawable(anim);
anim.start();
}
}
|
希望本文所述對大家Android程序設計有所幫助。