gif圖動畫在android中還是比較常用的,比如像新浪微網誌中,有很多gif圖檔,而且展示非常好,是以我也想弄一個。經過我多方的搜尋資料和整理,終于弄出來了,其實github上有很多開源的gif的展示代碼,我下載下傳過幾個,但是都不是很理想,不是我完全想要的。是以有時候就得自己學會總結,把開源的東西整理成自己的,現在無聊,也正好有朋友需要,是以現在整理了一下,留着以後備用!
廢話不多說,直接上圖:
在這裡主要用的是:android中的android.graphics.movie 這個類,這是android提供給我們的一個非常友善的工具。
首先,重寫控件view,自定義一個展示gif圖的gifview,代碼如下:
package net.loonggg.gif.view;
import net.loonggg.gif.r;
import android.annotation.suppresslint;
import android.content.context;
import android.content.res.typedarray;
import android.graphics.canvas;
import android.graphics.movie;
import android.os.build;
import android.util.attributeset;
import android.view.view;
public class gifview extends view {
/**
* 預設為1秒
*/
private static final int default_movie_duration = 1000;
private int mmovieresourceid;
private movie mmovie;
private long mmoviestart;
private int mcurrentanimationtime = 0;
private float mleft;
private float mtop;
private float mscale;
private int mmeasuredmoviewidth;
private int mmeasuredmovieheight;
private boolean mvisible = true;
private volatile boolean mpaused = false;
public gifview(context context) {
this(context, null);
}
public gifview(context context, attributeset attrs) {
this(context, attrs, r.styleable.customtheme_gifviewstyle);
public gifview(context context, attributeset attrs, int defstyle) {
super(context, attrs, defstyle);
setviewattributes(context, attrs, defstyle);
@suppresslint("newapi")
private void setviewattributes(context context, attributeset attrs,
int defstyle) {
if (build.version.sdk_int >= build.version_codes.honeycomb) {
setlayertype(view.layer_type_software, null);
}
// 從描述檔案中讀出gif的值,建立出movie執行個體
final typedarray array = context.obtainstyledattributes(attrs,
r.styleable.gifview, defstyle, r.style.widget_gifview);
mmovieresourceid = array.getresourceid(r.styleable.gifview_gif, -1);
mpaused = array.getboolean(r.styleable.gifview_paused, false);
array.recycle();
if (mmovieresourceid != -1) {
mmovie = movie.decodestream(getresources().openrawresource(
mmovieresourceid));
* 設定gif圖資源
*
* @param movieresid
public void setmovieresource(int movieresid) {
this.mmovieresourceid = movieresid;
mmovie = movie.decodestream(getresources().openrawresource(
mmovieresourceid));
requestlayout();
public void setmovie(movie movie) {
this.mmovie = movie;
public movie getmovie() {
return mmovie;
public void setmovietime(int time) {
mcurrentanimationtime = time;
invalidate();
* 設定暫停
* @param paused
public void setpaused(boolean paused) {
this.mpaused = paused;
if (!paused) {
mmoviestart = android.os.systemclock.uptimemillis()
- mcurrentanimationtime;
* 判斷gif圖是否停止了
* @return
public boolean ispaused() {
return this.mpaused;
@override
protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
if (mmovie != null) {
int moviewidth = mmovie.width();
int movieheight = mmovie.height();
int maximumwidth = measurespec.getsize(widthmeasurespec);
float scalew = (float) moviewidth / (float) maximumwidth;
mscale = 1f / scalew;
mmeasuredmoviewidth = maximumwidth;
mmeasuredmovieheight = (int) (movieheight * mscale);
setmeasureddimension(mmeasuredmoviewidth, mmeasuredmovieheight);
} else {
setmeasureddimension(getsuggestedminimumwidth(),
getsuggestedminimumheight());
protected void onlayout(boolean changed, int l, int t, int r, int b) {
super.onlayout(changed, l, t, r, b);
mleft = (getwidth() - mmeasuredmoviewidth) / 2f;
mtop = (getheight() - mmeasuredmovieheight) / 2f;
mvisible = getvisibility() == view.visible;
protected void ondraw(canvas canvas) {
if (!mpaused) {
updateanimationtime();
drawmovieframe(canvas);
invalidateview();
} else {
}
private void invalidateview() {
if (mvisible) {
if (build.version.sdk_int >= build.version_codes.jelly_bean) {
postinvalidateonanimation();
invalidate();
private void updateanimationtime() {
long now = android.os.systemclock.uptimemillis();
// 如果第一幀,記錄起始時間
if (mmoviestart == 0) {
mmoviestart = now;
// 取出動畫的時長
int dur = mmovie.duration();
if (dur == 0) {
dur = default_movie_duration;
// 算出需要顯示第幾幀
mcurrentanimationtime = (int) ((now - mmoviestart) % dur);
private void drawmovieframe(canvas canvas) {
// 設定要顯示的幀,繪制即可
mmovie.settime(mcurrentanimationtime);
canvas.save(canvas.matrix_save_flag);
canvas.scale(mscale, mscale);
mmovie.draw(canvas, mleft / mscale, mtop / mscale);
canvas.restore();
public void onscreenstatechanged(int screenstate) {
super.onscreenstatechanged(screenstate);
mvisible = screenstate == screen_state_on;
invalidateview();
protected void onvisibilitychanged(view changedview, int visibility) {
super.onvisibilitychanged(changedview, visibility);
mvisible = visibility == view.visible;
protected void onwindowvisibilitychanged(int visibility) {
super.onwindowvisibilitychanged(visibility);
}
movie其實管理着gif動畫中的多個幀,隻需要通過 settime() 一下就可以讓它在draw()的時候繪出相應的那幀圖像。通過目前時間與duration之間的換算關系,是很容易實作gif動起來的效果。
其次,在xml布局檔案中,把這個view定義進去,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<net.loonggg.gif.view.gifview
android:id="@+id/gif1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_gravity="center_horizontal"
android:enabled="false" />
android:id="@+id/gif2"
android:layout_width="200dp"
android:layout_height="200dp"
</linearlayout>
最後,在mainactivity中的使用,代碼如下:
package net.loonggg.gif;
import net.loonggg.gif.view.gifview;
import android.app.activity;
import android.os.bundle;
public class gif extends activity {
private gifview gif1, gif2;
public void oncreate(bundle savedinstancestate) {
super.oncreate(savedinstancestate);
setcontentview(r.layout.main);
gif1 = (gifview) findviewbyid(r.id.gif1);
// 設定背景gif圖檔資源
gif1.setmovieresource(r.raw.kitty);
gif2 = (gifview) findviewbyid(r.id.gif2);
gif2.setmovieresource(r.raw.b);
// 設定暫停
// gif2.setpaused(true);
注意:與imageview和其他view唯一的差別在于我加了一個gif屬性。
<resources>
<declare-styleable name="gifview">
<attr name="gif" format="reference" />
<attr name="paused" format="boolean" />
</declare-styleable>
<declare-styleable name="customtheme">
<attr name="gifviewstyle" format="reference" />
</resources>
這個代碼已經非常好了,使用也非常友善,其實不懂代碼是什麼意思也可以很好的用,隻需要懂得我寫注釋的那幾行和activity裡面的那幾行代碼就可以了!
轉載請注明出處:http://blog.csdn.net/loongggdroid/article/details/21166563