Android動(dòng)畫(huà)之逐幀動(dòng)畫(huà)(Frame Animation)實(shí)例詳解
本文實(shí)例分析了Android動(dòng)畫(huà)之逐幀動(dòng)畫(huà)。分享給大家供大家參考,具體如下:
在開(kāi)始實(shí)例講解之前,先引用官方文檔中的一段話:
Frame動(dòng)畫(huà)是一系列圖片按照一定的順序展示的過(guò)程,和放電影的機(jī)制很相似,我們稱為逐幀動(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文件中的話,語(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的話,此動(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展示給用戶時(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ù)資源名稱和目錄獲取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設(shè)備與外接U盤(pán)實(shí)現(xiàn)數(shù)據(jù)讀取操作的示例
本篇文章主要介紹了Android設(shè)備與外接U盤(pán)實(shí)現(xiàn)數(shù)據(jù)讀取操作的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-11-11Android RecyclerView上拉加載和下拉刷新(基礎(chǔ)版)
這篇文章主要為大家詳細(xì)介紹了Android RecyclerView上拉加載和下拉刷新的相實(shí)現(xiàn)方法,內(nèi)容簡(jiǎn)單,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-02-02簡(jiǎn)單實(shí)現(xiàn)Android端搜索框示例詳解
這篇文章主要為大家介紹了簡(jiǎn)單實(shí)現(xiàn)Android端搜索框示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11android基于socket的局域網(wǎng)內(nèi)服務(wù)器與客戶端加密通信
本篇文章主要介紹了android基于socket的局域網(wǎng)內(nèi)服務(wù)器與客戶端加密通信,這里整理了詳細(xì)的代碼,有需要的小伙伴可以參考下。2017-04-04Android實(shí)現(xiàn)原生鎖屏頁(yè)面音樂(lè)控制
這篇文章主要介紹了Android實(shí)現(xiàn)原生鎖屏頁(yè)面音樂(lè)控制,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-12-12