android 帧动画的使用
今天,簡(jiǎn)單講講android里如何使用幀動(dòng)畫(huà)。
其實(shí)也很簡(jiǎn)單,不過(guò)之前自己需要寫(xiě)一個(gè)幀動(dòng)畫(huà)時(shí),忘記了具體怎么寫(xiě),在網(wǎng)上查找資料后,解決了這個(gè)問(wèn)題。所以這里記錄一下。
一、概述
幀動(dòng)畫(huà),顧名思義就是這個(gè)動(dòng)畫(huà)的效果是由一幀幀的圖片組合出來(lái)的。通過(guò)制定圖片展示的順序,達(dá)到動(dòng)畫(huà)的展示效果。
在Android開(kāi)發(fā)中,系統(tǒng)給我們提供了”animation-list” 節(jié)點(diǎn)用于我們配置幀動(dòng)畫(huà)。
一.使用xml實(shí)現(xiàn)幀動(dòng)畫(huà)
實(shí)現(xiàn)步驟
1、在res目錄下創(chuàng)建用于存儲(chǔ)xml動(dòng)畫(huà)文件的anim文件夾,res/anim,也可以放在drawable目錄下
具體代碼如下:
<?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="false"><itemandroid:drawable="@mipmap/sample_1"android:duration="100" /><itemandroid:drawable="@mipmap/sample_2"android:duration="100" /><itemandroid:drawable="@mipmap/sample_3"android:duration="100" /><itemandroid:drawable="@mipmap/sample_4"android:duration="100" /><itemandroid:drawable="@mipmap/sample_5"android:duration="100" /><itemandroid:drawable="@mipmap/sample_6"android:duration="100" /> </animation-list>簡(jiǎn)單講講,這里提供了6張圖片,每張圖片顯示100毫秒進(jìn)行切換,其中android:oneshot="false" 是設(shè)置是否循環(huán)播放,默認(rèn)的是循環(huán)播放,true為只播放一次
2、將文件設(shè)置到ImageView控件的背景上,然后獲取背景轉(zhuǎn)換為AnimationDrawable對(duì)象進(jìn)行播放動(dòng)畫(huà)
iv_imageView.setBackgroundResource(R.drawable.frame_animation);AnimationDrawable animation = (AnimationDrawable)iv_imageView.getBackground();animation.start();如果想要停止播放動(dòng)畫(huà)可以調(diào)用AnimationDrawable的stop方法
二.直接使用java代碼創(chuàng)建幀動(dòng)畫(huà)
public class MainActivity extends AppCompatActivity {private ImageView iv_ani;private AnimationDrawable mAnimationDrawable;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);iv_ani = (ImageView) findViewById(R.id.iv_ani);initAnimationDrawable();}private void initAnimationDrawable(){mAnimationDrawable = new AnimationDrawable();for (int i = 1; i <= 4; i++) {int id = getResources().getIdentifier("sample_" + i, "mipmap", getPackageName());Drawable drawable = getResources().getDrawable(id);mAnimationDrawable.addFrame(drawable, 100);}mAnimationDrawable.setOneShot(false);iv_ani.setImageDrawable(mAnimationDrawable);} }addFrame(Drawable frame, int duration) : 添加一幀,并設(shè)置該幀顯示的持續(xù)時(shí)間
接下來(lái)簡(jiǎn)單介紹幀動(dòng)畫(huà)的原理,大家有興趣的可以看看。
三、幀動(dòng)畫(huà)原理分析
在上面的開(kāi)發(fā)中,我們?cè)趯ackgroud對(duì)應(yīng)的Drawable對(duì)象轉(zhuǎn)換為一個(gè)AnimationDrawable對(duì)象,然后由這個(gè)對(duì)象啟動(dòng)Frame動(dòng)畫(huà),那么這個(gè)類究竟是由何方神圣呢?讓我們一起look look。
1、AnimationDrawable概述
AnimationDrawable用于創(chuàng)建frame-by-frame(逐幀)動(dòng)畫(huà),它定義了一些列的Drawable對(duì)象可用于設(shè)置View的backgroud背景屬性。frame-by-frame動(dòng)畫(huà)最簡(jiǎn)單的方式是通過(guò)XML文件進(jìn)行創(chuàng)建,然后將xml文件放到res/drawable/folder文件夾下,同時(shí)將此drawa對(duì)象設(shè)置到view的backgroud屬性。Xml文件的組成:
animation-list:根節(jié)點(diǎn),包含一系列的item item:每個(gè)item對(duì)應(yīng)一個(gè)frame(幀)
下面是在代碼中創(chuàng)建和使用幀動(dòng)畫(huà):
ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);img.setBackgroundResource(R.drawable.spin_animation);AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();frameAnimation.start();我們?cè)趤?lái)看看AnimationDrawable對(duì)象給我們提供的屬性。
AnimationDrawable_visible:設(shè)置是否可見(jiàn) AnimationDrawable_variablePadding: AnimationDrawable_oneshot:設(shè)置是否只播放一次,true是,false否 AnimationDrawableItem_duration:設(shè)置每幀動(dòng)畫(huà)之間的時(shí)間間隔 AnimationDrawableItem_drawable:設(shè)置每幀之間間隔的drawable對(duì)象
2、AnimationDrawable源碼分析
上面我們已經(jīng)對(duì)AnimationDrawable進(jìn)行了一個(gè)簡(jiǎn)要的分析,了解了一些它的屬性,我們心中獲取對(duì)幀動(dòng)畫(huà)還有一些疑惑,比如一些問(wèn)題:
AnimationDrawable是如何形成一個(gè)個(gè)幀畫(huà)面? Frame Animation是如何實(shí)現(xiàn)不斷循環(huán)播放? 我們能否通過(guò)代碼控制Frame動(dòng)畫(huà)的播放?
下面我們就圍繞上面的幾個(gè)問(wèn)題對(duì)AnimationdDrawable進(jìn)行分析。查看源碼,我們可以看到AnimationDrawable暴露的public方法。
AnimationDrawable根據(jù)名稱,我們也能推算到這是一個(gè)Drawable的子類,我們仔細(xì)一想,為什么通過(guò)getBackgroud()方法獲得的Drawable對(duì)象可以轉(zhuǎn)換到AnimationDrawable這個(gè)子類呢?這就需要我們?nèi)タ聪略创a。在Drawable類中,有一個(gè)方法createFromXml()方法:
/*** Create a drawable from an XML document. For more information on how to* create resources in XML, see* Drawable Resources.*/public static Drawable createFromXml(Resources r, XmlPullParser parser)throws XmlPullParserException, IOException {return createFromXml(r, parser, null);}
這個(gè)方法就是用于將我的XML文件轉(zhuǎn)換成一個(gè)drawable對(duì)象,我們接著深入下去,看下createFromXml()這個(gè)方法。
public static Drawable createFromXml(Resources r, XmlPullParser parser, Theme theme)throws XmlPullParserException, IOException {AttributeSet attrs = Xml.asAttributeSet(parser);int type;while ((type=parser.next()) != XmlPullParser.START_TAG &&type != XmlPullParser.END_DOCUMENT) {// Empty loop}if (type != XmlPullParser.START_TAG) {throw new XmlPullParserException("No start tag found");}Drawable drawable = createFromXmlInner(r, parser, attrs, theme);if (drawable == null) {throw new RuntimeException("Unknown initial tag: " + parser.getName());}return drawable;}
在這里我們看到了XML文件轉(zhuǎn)換成Drawable的內(nèi)部,在Android系統(tǒng)中,同樣是通過(guò)XmlPullParser進(jìn)行Xml文件的解析,在上面的方法中,首先進(jìn)行xml文件的開(kāi)始標(biāo)簽和結(jié)束標(biāo)簽,判斷xml文件內(nèi)部是否為空節(jié)點(diǎn)。然后通過(guò):
Drawable drawable = createFromXmlInner(r, parser, attrs, theme);
進(jìn)行XML文件解析,最后轉(zhuǎn)換成Drawable對(duì)象。
在createFromXmlInner方法中,首先獲取我們都xml文件的標(biāo)簽,然后根絕我們對(duì)應(yīng)的標(biāo)簽名稱創(chuàng)建對(duì)應(yīng)的drawable對(duì)象,比如我們這次創(chuàng)建的AnimationDrawable對(duì)象。然后調(diào)用inflater()方法,由于AnimationDrawable方法中已經(jīng)對(duì)inflater方法進(jìn)行了重寫(xiě),所以此時(shí)這個(gè)就是:
至此,我們已經(jīng)基本理清了從XML文件到Drawable對(duì)象的轉(zhuǎn)換流程,現(xiàn)在我們就開(kāi)始分析animation-list節(jié)點(diǎn)下的節(jié)點(diǎn)如何形成一個(gè)個(gè)幀動(dòng)畫(huà)效果的。在進(jìn)行分析之前,我們先了解下AnimationState類。這個(gè)類用于存儲(chǔ)我們的一系列drawable。通過(guò)源碼發(fā)現(xiàn):
private final static class AnimationState extends DrawableContainerState
這個(gè)類繼承DrawableContainerState類,DrawableContainerState中有一個(gè)成員變量Drawable[] mDrawables;用于存儲(chǔ)我們的drawable信息。明白這一點(diǎn),我們就可以分析方法inflateChildElements方法。
在這方法里面通過(guò)TypeArray獲取drawable的相關(guān)信息,然后調(diào)用mAnimationState的addFrame方法,將一系列動(dòng)畫(huà)信息就存儲(chǔ)在drawable數(shù)組中。
通過(guò)上面的分析,一系列的動(dòng)畫(huà)已經(jīng)轉(zhuǎn)出并進(jìn)行了存儲(chǔ),我們接下來(lái)的任務(wù)就是進(jìn)行start的分析,分析動(dòng)畫(huà)的開(kāi)啟。
通過(guò)setFrame方法設(shè)置我們的drawable,里面有selectDrawable(frame)進(jìn)行設(shè)置
這里簡(jiǎn)單講講,幀動(dòng)畫(huà)其實(shí)就是解析xml文件獲取drawable,然后一次加載到內(nèi)存,進(jìn)行顯示。所以幀動(dòng)畫(huà)的圖片不要過(guò)度,會(huì)導(dǎo)致內(nèi)存使用過(guò)大。
android 幀動(dòng)畫(huà)的使用就講完了。
就這么簡(jiǎn)單。
總結(jié)
以上是生活随笔為你收集整理的android 帧动画的使用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: android Drawable.mut
- 下一篇: android handler 的rem