Android動(dòng)畫(huà)之逐幀動(dòng)畫(huà)(Frame Animation)實(shí)例詳解
本文實(shí)例分析了Android動(dòng)畫(huà)之逐幀動(dòng)畫(huà)。分享給大家供大家參考,具體如下:
在開(kāi)始實(shí)例講解之前,先引用官方文檔中的一段話(huà):
Frame動(dòng)畫(huà)是一系列圖片按照一定的順序展示的過(guò)程,和放電影的機(jī)制很相似,我們稱(chēng)為逐幀動(dòng)畫(huà)。Frame動(dòng)畫(huà)可以被定義在XML文件中,也可以完全編碼實(shí)現(xiàn)。
如果被定義在XML文件中,我們可以放置在/res下的anim或drawable目錄中(/res/[anim | drawable]/filename.xml),文件名可以作為資源ID在代碼中引用;如果由完全由編碼實(shí)現(xiàn),我們需要使用到AnimationDrawable對(duì)象。
如果是將動(dòng)畫(huà)定義在XML文件中的話(huà),語(yǔ)法如下:
<?xml version="1.0" encoding="utf-8"?>
<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>元素是必須的,并且必須要作為根元素,可以包含一或多個(gè)<item>元素;android:onshot如果定義為true的話(huà),此動(dòng)畫(huà)只會(huì)執(zhí)行一次,如果為false則一直循環(huán)。
<item>元素代表一幀動(dòng)畫(huà),android:drawable指定此幀動(dòng)畫(huà)所對(duì)應(yīng)的圖片資源,android:druation代表此幀持續(xù)的時(shí)間,整數(shù),單位為毫秒。
文檔接下來(lái)的示例我就不在解說(shuō)了,因?yàn)榻酉聛?lái)我們也要結(jié)合自己的實(shí)例演示一下這個(gè)過(guò)程。
我們新建一個(gè)名為anim的工程,將四張連續(xù)的圖片分別命名為f1.png,f2.png,f3.png,f4.png,放于drawable目錄,然后新建一個(gè)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/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中了,大家可以根據(jù)喜好來(lái)放置,放在這兩個(gè)目錄都是可以運(yùn)行的。
然后介紹一下布局文件res/layout/frame.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 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>
我們定義了一個(gè)ImageView作為動(dòng)畫(huà)的載體,然后定義了兩個(gè)按鈕,分別是停止和啟動(dòng)動(dòng)畫(huà)。
接下來(lái)介紹一下如何通過(guò)加載動(dòng)畫(huà)定義文件來(lái)實(shí)現(xiàn)動(dòng)畫(huà)的效果。我們首先會(huì)這樣寫(xiě):
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();
}
}
看似十分完美,跟官方文檔上寫(xiě)的一樣,然而當(dāng)我們運(yùn)行這個(gè)程序時(shí)會(huì)發(fā)現(xiàn),它只停留在第一幀,并沒(méi)有出現(xiàn)我們期望的動(dòng)畫(huà),也許你會(huì)失望的說(shuō)一句:“Why?”,然后你把相應(yīng)的代碼放在一個(gè)按鈕的點(diǎn)擊事件中,動(dòng)畫(huà)就順利執(zhí)行了,再移回到onCreate中,還是沒(méi)效果,這個(gè)時(shí)候估計(jì)你會(huì)氣急敗壞的吼一句:“What the fuck!”。但是,什么原因呢?如何解決呢?
出現(xiàn)這種現(xiàn)象是因?yàn)楫?dāng)我們?cè)趏nCreate中調(diào)用AnimationDrawable的start方法時(shí),窗口Window對(duì)象還沒(méi)有完全初始化,AnimationDrawable不能完全追加到窗口Window對(duì)象中,那么該怎么辦呢?我們需要把這段代碼放在onWindowFocusChanged方法中,當(dāng)Activity展示給用戶(hù)時(shí),onWindowFocusChanged方法就會(huì)被調(diào)用,我們正是在這個(gè)時(shí)候?qū)崿F(xiàn)我們的動(dòng)畫(huà)效果。當(dāng)然,onWindowFocusChanged是在onCreate之后被調(diào)用的,如圖:
然后我們需要重寫(xiě)一下代碼:
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();
}
}
運(yùn)行一下,動(dòng)畫(huà)就可以正常顯示了。
如果在有些場(chǎng)合,我們需要用純代碼方式實(shí)現(xiàn)一個(gè)動(dòng)畫(huà),我們可以這樣寫(xiě):
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代碼如下:
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); //將動(dòng)畫(huà)資源文件設(shè)置為ImageView的背景
AnimationDrawable anim = (AnimationDrawable) image.getBackground(); //獲取ImageView背景,此時(shí)已被編譯成AnimationDrawable
anim.start(); //開(kāi)始動(dòng)畫(huà)
}
public void stopFrame(View view) {
AnimationDrawable anim = (AnimationDrawable) image.getBackground();
if (anim.isRunning()) { //如果正在運(yùn)行,就停止
anim.stop();
}
}
public void runFrame(View view) {
//完全編碼實(shí)現(xiàn)的動(dòng)畫(huà)效果
AnimationDrawable anim = new AnimationDrawable();
for (int i = 1; i <= 4; i++) {
//根據(jù)資源名稱(chēng)和目錄獲取R.java中對(duì)應(yīng)的資源ID
int id = getResources().getIdentifier("f" + i, "drawable", getPackageName());
//根據(jù)資源ID獲取到Drawable對(duì)象
Drawable drawable = getResources().getDrawable(id);
//將此幀添加到AnimationDrawable中
anim.addFrame(drawable, 300);
}
anim.setOneShot(false); //設(shè)置為loop
image.setBackgroundDrawable(anim); //將動(dòng)畫(huà)設(shè)置為ImageView背景
anim.start(); //開(kāi)始動(dòng)畫(huà)
}
}
希望本文所述對(duì)大家Android程序設(shè)計(jì)有所幫助。
- Android 動(dòng)畫(huà)(View動(dòng)畫(huà),幀動(dòng)畫(huà),屬性動(dòng)畫(huà))詳細(xì)介紹
- Android逐幀動(dòng)畫(huà)實(shí)現(xiàn)代碼
- Android 使用幀動(dòng)畫(huà)內(nèi)存溢出解決方案
- Android之仿美團(tuán)加載數(shù)據(jù)幀動(dòng)畫(huà)
- Android動(dòng)畫(huà)之逐幀動(dòng)畫(huà)(Frame Animation)基礎(chǔ)學(xué)習(xí)
- Android幀動(dòng)畫(huà)、補(bǔ)間動(dòng)畫(huà)、屬性動(dòng)畫(huà)用法詳解
- Android編程之簡(jiǎn)單逐幀動(dòng)畫(huà)Frame的實(shí)現(xiàn)方法
- Android 幀動(dòng)畫(huà)的實(shí)例詳解
- Android 逐幀動(dòng)畫(huà)創(chuàng)建實(shí)例詳解
- Android Studio實(shí)現(xiàn)幀動(dòng)畫(huà)
相關(guān)文章
Android RecyclerView的Item自定義動(dòng)畫(huà)及DefaultItemAnimator源碼分析
這篇文章主要介紹了Android RecyclerView的Item自定義動(dòng)畫(huà)及DefaultItemAnimator源碼,感興趣的小伙伴們可以參考一下2016-07-07
Android SQLite事務(wù)處理結(jié)合Listview列表顯示功能示例
這篇文章主要介紹了Android SQLite事務(wù)處理結(jié)合Listview列表顯示功能,較為詳細(xì)的分析了Android使用sqlite數(shù)據(jù)庫(kù)進(jìn)行事務(wù)操作并結(jié)合Listview進(jìn)行列表顯示的相關(guān)操作技巧,需要的朋友可以參考下2017-07-07
Android實(shí)現(xiàn)點(diǎn)擊兩次BACK鍵退出應(yīng)用
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)點(diǎn)擊兩次BACK鍵退出應(yīng)用的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-09-09
Android實(shí)現(xiàn)垂直進(jìn)度條VerticalSeekBar
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)垂直進(jìn)度條VerticalSeekBar的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07
Android Toast實(shí)現(xiàn)全屏顯示
這篇文章主要為大家詳細(xì)介紹了Android Toast實(shí)現(xiàn)全屏顯示,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-08-08
Android使用個(gè)推實(shí)現(xiàn)三方應(yīng)用的推送功能
這篇文章主要為大家詳細(xì)介紹了Android使用個(gè)推實(shí)現(xiàn)三方應(yīng)用的推送功能,感興趣的小伙伴們可以參考一下2016-08-08
Android編程之計(jì)時(shí)器Chronometer簡(jiǎn)單示例
這篇文章主要介紹了Android計(jì)時(shí)器Chronometer簡(jiǎn)單用法,結(jié)合實(shí)例形式分析了Android計(jì)時(shí)器Chronometer的定義、事件響應(yīng)及界面布局相關(guān)操作技巧,需要的朋友可以參考下2017-08-08

