日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

android 帧动画的使用

發(fā)布時間:2024/4/15 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android 帧动画的使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.



今天,簡單講講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方法

iv_imageView.setBackgroundResource(R.drawable.frame_animation);AnimationDrawable animation = (AnimationDrawable)iv_imageView.getBackground();animation.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對象。

public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,Theme theme) throws XmlPullParserException, IOException {final Drawable drawable;final String name = parser.getName();switch (name) {case "selector":drawable = new StateListDrawable();break;case "animated-selector":drawable = new AnimatedStateListDrawable();break;case "level-list":drawable = new LevelListDrawable();break;case "layer-list":drawable = new LayerDrawable();break;case "transition":drawable = new TransitionDrawable();break;case "ripple":drawable = new RippleDrawable();break;case "color":drawable = new ColorDrawable();break;case "shape":drawable = new GradientDrawable();break;case "vector":drawable = new VectorDrawable();break;case "animated-vector":drawable = new AnimatedVectorDrawable();break;case "scale":drawable = new ScaleDrawable();break;case "clip":drawable = new ClipDrawable();break;case "rotate":drawable = new RotateDrawable();break;case "animated-rotate":drawable = new AnimatedRotateDrawable();break;case "animation-list":drawable = new AnimationDrawable();break;case "inset":drawable = new InsetDrawable();break;case "bitmap":drawable = new BitmapDrawable();break;case "nine-patch":drawable = new NinePatchDrawable();break;default:throw new XmlPullParserException(parser.getPositionDescription() +": invalid drawable tag " + name);}drawable.inflate(r, parser, attrs, theme);return 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)行了重寫,所以此時這個就是:

@Overridepublic void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)throws XmlPullParserException, IOException {final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable);super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible);updateStateFromTypedArray(a);a.recycle();inflateChildElements(r, parser, attrs, theme);setFrame(0, true, false);}


至此,我們已經(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方法。

private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,Theme theme) throws XmlPullParserException, IOException {int type;final int innerDepth = parser.getDepth()+1;int depth;while ((type=parser.next()) != XmlPullParser.END_DOCUMENT&& ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {if (type != XmlPullParser.START_TAG) {continue;}if (depth > innerDepth || !parser.getName().equals("item")) {continue;}final TypedArray a = obtainAttributes(r, theme, attrs,R.styleable.AnimationDrawableItem);final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1);if (duration < 0) {throw new XmlPullParserException(parser.getPositionDescription()+ ": <item> tag requires a 'duration' attribute");}Drawable dr = a.getDrawable(R.styleable.AnimationDrawableItem_drawable);a.recycle();if (dr == null) {while ((type=parser.next()) == XmlPullParser.TEXT) {// Empty}if (type != XmlPullParser.START_TAG) {throw new XmlPullParserException(parser.getPositionDescription()+ ": <item> tag requires a 'drawable' attribute or child tag"+ " defining a drawable");}dr = Drawable.createFromXmlInner(r, parser, attrs, theme);}mAnimationState.addFrame(dr, duration);if (dr != null) {dr.setCallback(this);}}}

在這方法里面通過TypeArray獲取drawable的相關(guān)信息,然后調(diào)用mAnimationState的addFrame方法,將一系列動畫信息就存儲在drawable數(shù)組中。

  通過上面的分析,一系列的動畫已經(jīng)轉(zhuǎn)出并進(jìn)行了存儲,我們接下來的任務(wù)就是進(jìn)行start的分析,分析動畫的開啟。

public void start() {mAnimating = true;if (!isRunning()) {// Start from 0th frame.setFrame(0, false, mAnimationState.getChildCount() > 1|| !mAnimationState.mOneShot);}}


通過setFrame方法設(shè)置我們的drawable,里面有selectDrawable(frame)進(jìn)行設(shè)置


這里簡單講講,幀動畫其實就是解析xml文件獲取drawable,然后一次加載到內(nèi)存,進(jìn)行顯示。所以幀動畫的圖片不要過度,會導(dǎo)致內(nèi)存使用過大。


android 幀動畫的使用就講完了。


就這么簡單。



總結(jié)

以上是生活随笔為你收集整理的android 帧动画的使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。