android 帧动画的使用
今天,簡單講講android里如何使用幀動畫。
其實也很簡單,不過之前自己需要寫一個幀動畫時,忘記了具體怎么寫,在網(wǎng)上查找資料后,解決了這個問題。所以這里記錄一下。
一、概述
幀動畫,顧名思義就是這個動畫的效果是由一幀幀的圖片組合出來的。通過制定圖片展示的順序,達(dá)到動畫的展示效果。
在Android開發(fā)中,系統(tǒng)給我們提供了”animation-list” 節(jié)點(diǎn)用于我們配置幀動畫。
一.使用xml實現(xiàn)幀動畫
實現(xiàn)步驟
1、在res目錄下創(chuàng)建用于存儲xml動畫文件的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>簡單講講,這里提供了6張圖片,每張圖片顯示100毫秒進(jìn)行切換,其中android:oneshot="false" 是設(shè)置是否循環(huán)播放,默認(rèn)的是循環(huán)播放,true為只播放一次
2、將文件設(shè)置到ImageView控件的背景上,然后獲取背景轉(zhuǎn)換為AnimationDrawable對象進(jìn)行播放動畫
iv_imageView.setBackgroundResource(R.drawable.frame_animation);AnimationDrawable animation = (AnimationDrawable)iv_imageView.getBackground();animation.start();如果想要停止播放動畫可以調(diào)用AnimationDrawable的stop方法
二.直接使用java代碼創(chuàng)建幀動畫
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ù)時間
接下來簡單介紹幀動畫的原理,大家有興趣的可以看看。
三、幀動畫原理分析
在上面的開發(fā)中,我們在將backgroud對應(yīng)的Drawable對象轉(zhuǎn)換為一個AnimationDrawable對象,然后由這個對象啟動Frame動畫,那么這個類究竟是由何方神圣呢?讓我們一起look look。
1、AnimationDrawable概述
AnimationDrawable用于創(chuàng)建frame-by-frame(逐幀)動畫,它定義了一些列的Drawable對象可用于設(shè)置View的backgroud背景屬性。frame-by-frame動畫最簡單的方式是通過XML文件進(jìn)行創(chuàng)建,然后將xml文件放到res/drawable/folder文件夾下,同時將此drawa對象設(shè)置到view的backgroud屬性。Xml文件的組成:
animation-list:根節(jié)點(diǎn),包含一系列的item item:每個item對應(yīng)一個frame(幀)
下面是在代碼中創(chuàng)建和使用幀動畫:
ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);img.setBackgroundResource(R.drawable.spin_animation);AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();frameAnimation.start();我們在來看看AnimationDrawable對象給我們提供的屬性。
AnimationDrawable_visible:設(shè)置是否可見 AnimationDrawable_variablePadding: AnimationDrawable_oneshot:設(shè)置是否只播放一次,true是,false否 AnimationDrawableItem_duration:設(shè)置每幀動畫之間的時間間隔 AnimationDrawableItem_drawable:設(shè)置每幀之間間隔的drawable對象
2、AnimationDrawable源碼分析
上面我們已經(jīng)對AnimationDrawable進(jìn)行了一個簡要的分析,了解了一些它的屬性,我們心中獲取對幀動畫還有一些疑惑,比如一些問題:
AnimationDrawable是如何形成一個個幀畫面? Frame Animation是如何實現(xiàn)不斷循環(huán)播放? 我們能否通過代碼控制Frame動畫的播放?
下面我們就圍繞上面的幾個問題對AnimationdDrawable進(jìn)行分析。查看源碼,我們可以看到AnimationDrawable暴露的public方法。
AnimationDrawable根據(jù)名稱,我們也能推算到這是一個Drawable的子類,我們仔細(xì)一想,為什么通過getBackgroud()方法獲得的Drawable對象可以轉(zhuǎn)換到AnimationDrawable這個子類呢?這就需要我們?nèi)タ聪略创a。在Drawable類中,有一個方法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);}
這個方法就是用于將我的XML文件轉(zhuǎn)換成一個drawable對象,我們接著深入下去,看下createFromXml()這個方法。
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)中,同樣是通過XmlPullParser進(jìn)行Xml文件的解析,在上面的方法中,首先進(jìn)行xml文件的開始標(biāo)簽和結(jié)束標(biāo)簽,判斷xml文件內(nèi)部是否為空節(jié)點(diǎn)。然后通過:
Drawable drawable = createFromXmlInner(r, parser, attrs, theme);
進(jìn)行XML文件解析,最后轉(zhuǎn)換成Drawable對象。
在createFromXmlInner方法中,首先獲取我們都xml文件的標(biāo)簽,然后根絕我們對應(yīng)的標(biāo)簽名稱創(chuàng)建對應(yīng)的drawable對象,比如我們這次創(chuàng)建的AnimationDrawable對象。然后調(diào)用inflater()方法,由于AnimationDrawable方法中已經(jīng)對inflater方法進(jìn)行了重寫,所以此時這個就是:
至此,我們已經(jīng)基本理清了從XML文件到Drawable對象的轉(zhuǎn)換流程,現(xiàn)在我們就開始分析animation-list節(jié)點(diǎn)下的節(jié)點(diǎn)如何形成一個個幀動畫效果的。在進(jìn)行分析之前,我們先了解下AnimationState類。這個類用于存儲我們的一系列drawable。通過源碼發(fā)現(xiàn):
private final static class AnimationState extends DrawableContainerState
這個類繼承DrawableContainerState類,DrawableContainerState中有一個成員變量Drawable[] mDrawables;用于存儲我們的drawable信息。明白這一點(diǎn),我們就可以分析方法inflateChildElements方法。
在這方法里面通過TypeArray獲取drawable的相關(guān)信息,然后調(diào)用mAnimationState的addFrame方法,將一系列動畫信息就存儲在drawable數(shù)組中。
通過上面的分析,一系列的動畫已經(jīng)轉(zhuǎn)出并進(jìn)行了存儲,我們接下來的任務(wù)就是進(jìn)行start的分析,分析動畫的開啟。
通過setFrame方法設(shè)置我們的drawable,里面有selectDrawable(frame)進(jìn)行設(shè)置
這里簡單講講,幀動畫其實就是解析xml文件獲取drawable,然后一次加載到內(nèi)存,進(jìn)行顯示。所以幀動畫的圖片不要過度,會導(dǎo)致內(nèi)存使用過大。
android 幀動畫的使用就講完了。
就這么簡單。
總結(jié)
以上是生活随笔為你收集整理的android 帧动画的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android Drawable.mut
- 下一篇: android handler 的rem