天天看點

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

繼續閱讀