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