Android自定義GifView顯示gif動畫

jopen 9年前發布 | 59K 次閱讀 Android Android開發 移動開發

  gif動畫在web開發中使用的非常的多,利用gif,許多動畫不必再用程序編寫,現在有非常多的App已經使用到了gif動畫,可是android sdk并沒有為我們提供gif這種View,所以我們只能自定義一個View,去實現gif效果.

   android雖然沒有為我們提供現成的GifView,但是為我們提供了Movie類,這個類就是用來實現GifView的關鍵類.它主要有兩個最重要的方法,一個是根據動畫播放時間設置當前要現顯示的幀,二是將當前要顯示的幀繪制到畫布中.下面看一下效果圖:

點擊暫停按鈕還可以暫停gif動畫.

   下面就看是如何實現的:

    1.首先將需要用到的屬性先自定義好:如下代碼所示:

    <?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="gifCommon">  
        <attr name="gif_src" format="reference" />  
        <attr name="decode_stream" format="boolean" />  
        <attr name="default_animation_time" format="integer" />  
    </declare-styleable>  

</resources>  </pre><br />

三個屬性分別代表:gif資源,是否采用流編碼,默認動畫間隔時間.    2.自定義GifView代碼.

    package view;

import java.io.ByteArrayOutputStream;  
import java.io.InputStream;  

import android.content.Context;  
import android.content.res.TypedArray;  
import android.graphics.Canvas;  
import android.graphics.Movie;  
import android.util.AttributeSet;  
import android.view.View;  

import com.example.drawbaledemo.R;  

/** 
 * @author rzq 
 * 
 */  
public class GifView extends View {  

    private Movie mMovie;  
        /** 
         * 動畫開始時間 
         / 
        private long mMovieStart; 
    private boolean mPaused = false; 
        /** 
         * 當前幀動畫時間 
         / 
        private int mCurrentAnimationTime ; 
    /** 
         * 自定義的三個屬性 
         / 
        private boolean decode_STREAM; 
    private int src_ID; 
    private int default_time; 

    public GifView(Context context) { 
        super(context); 
        init(context, null); 
    } 

    public GifView(Context context, AttributeSet set) { 
        super(context, set); 
        init(context, set); 
    } 

    private void init(Context context, AttributeSet set) { 

        TypedArray a = context.obtainStyledAttributes(set, 
                R.styleable.gifCommon); 
        src_ID = a.getResourceId(R.styleable.gifCommon_gif_src, -1); 
        decode_STREAM = a.getBoolean(R.styleable.gifCommon_decode_stream, true); 
        default_time = a.getInteger( 
                R.styleable.gifCommon_default_animation_time, 1000); 
        a.recycle(); 

        setFocusable(true); 
        java.io.InputStream is; 
        is = context.getResources().openRawResource(src_ID); 

        if (decode_STREAM) { 
            mMovie = Movie.decodeStream(is);    // 根據文件流創建Movier繪制對象 
        } else { 
            byte[] array = streamToBytes(is); 
            mMovie = Movie.decodeByteArray(array, 0, array.length); 
        } 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
        if (mMovie != null) { 
            if (!mPaused) { 
                // 更新幀時間 
                updateAnimationTime(); 
                drawMovieFrame(canvas); 
                invalidate(); 
            } else { 
                // 暫停時,不更新幀時間,則只畫當前幀 
                drawMovieFrame(canvas); 
            } 
        } 
    } 

    private void updateAnimationTime() { 
        long now = android.os.SystemClock.uptimeMillis(); 
        // 如果第一幀,記錄起始時間 
        if (mMovieStart == 0) { 
            mMovieStart = now; 
        } 
        // 取出動畫的時長 
        int dur = mMovie.duration(); 
        if (dur == 0) { 
            dur = default_time; 
        } 
        // 算出需要顯示第幾幀 
        mCurrentAnimationTime = (int) ((now - mMovieStart) % dur); 
    } 

    private void drawMovieFrame(Canvas canvas) { 
        // 設置要顯示的幀,繪制即可 
        mMovie.setTime(mCurrentAnimationTime); 
        canvas.save(Canvas.MATRIX_SAVE_FLAG); 
        mMovie.draw(canvas, 0, 0); 
        canvas.restore(); 
    } 

    /** 
     * 設置暫停 
     *  
     * @param paused 
     */  
    public void setPaused(boolean paused) {  
        this.mPaused = paused;  
        if (!paused) {  
            /** 
             * 更新動畫起點時間 
             */  
            mMovieStart = android.os.SystemClock.uptimeMillis()  
                    - mCurrentAnimationTime;  
        }  
        invalidate();  
    }  

    /** 
     * 判斷gif圖是否停止了 
     *  
     * @return 
     */  
    public boolean isPaused() {  
        return this.mPaused;  
    }  

    /** 
     * 重寫此方法,使自定義View支持wrap_content 
     */  
    @Override  
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);  
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);  
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);  
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);  
        int width;  
        int height;  
        if (widthMode == MeasureSpec.EXACTLY) {  
            width = widthSize;  
        } else {  

            int desired = (int) (getPaddingLeft() + mMovie.width() + getPaddingRight());  
            width = Math.min(desired,widthSize);  
        }  

        if (heightMode == MeasureSpec.EXACTLY) {  
            height = heightSize;  
        } else {  
            int desired = (int) (getPaddingTop() + mMovie.height() + getPaddingBottom());  
            height = Math.min(desired,heightSize);  
        }  

        setMeasuredDimension(width, height);  
    }  

    /** 
     * 將流轉化為字節數組 
     *  
     * @param is 
     * @return 
     */  
    private static byte[] streamToBytes(InputStream is) {  
        ByteArrayOutputStream os = new ByteArrayOutputStream(1024);  
        byte[] buffer = new byte[1024];  
        int len;  
        try {  
            while ((len = is.read(buffer)) >= 0) {  
                os.write(buffer, 0, len);  
            }  
        } catch (java.io.IOException e) {  
        }  
        return os.toByteArray();  
    }  

}  </pre>  3.布局文件中使用GifView. <pre class="brush:xml; toolbar: true; auto-links: false;">    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    xmlns:tools="http://schemas.android.com/tools"  
    xmlns:gif="http://schemas.android.com/apk/res-auto"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent"  
    android:background="#fed952"  
    android:gravity="center" >  

    <view.GifView  
        android:id="@+id/gif_view"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:background="#ffffff"  
        gif:decode_stream="true"  
        gif:default_animation_time="1000"  
        gif:gif_src="@drawable/animated_gif" />  

    <TextView  
        android:id="@+id/btn"  
        android:layout_width="wrap_content"  
        android:layout_height="wrap_content"  
        android:layout_below="@+id/gif_view"  
        android:text="暫停" />  

</RelativeLayout>  </pre><br />

與使用普通的View一樣,將需要的資源傳入即可.

來自:http://blog.csdn.net/lcq5211314123/article/details/43492509

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!