天天看点

android GifView分享

gif图动画在android中还是比较常用的,比如像新浪微博中,有很多gif图片,而且展示非常好,所以我也想弄一个。经过我多方的搜索资料和整理,终于弄出来了,其实github上有很多开源的gif的展示代码,我下载过几个,但是都不是很理想,不是我完全想要的。所以有时候就得自己学会总结,把开源的东西整理成自己的,现在无聊,也正好有朋友需要,所以现在整理了一下,留着以后备用!

废话不多说,直接上图:

android GifView分享
android GifView分享

在这里主要用的是:android中的android.graphics.movie 这个类,这是android提供给我们的一个非常方便的工具。

首先,重写控件view,自定义一个展示gif图的gifview,代码如下:

android 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定义进去,代码如下:

android GifView分享

<?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中的使用,代码如下:

android GifView分享

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属性。

android GifView分享

<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

继续阅读