1. 程式人生 > >Android學習之ImageView放置gif動態圖

Android學習之ImageView放置gif動態圖

最近做圖片的時候碰到一個問題,就是imageview控制元件中放動態圖,顯示出來的效果跟靜態圖是一樣的。於是我網上大概找了一下資料,對於這方面大概有三個解決方法
一、將gif用工具分割,一幀一幀的播放

這篇部落格中有介紹http://www.cnblogs.com/TerryBlog/archive/2010/09/06/1819641.html

二、使用開源框架

Glide是個不錯的選擇,當然也還有其他的,下面這篇部落格,對於Glide講的還比較清晰
http://blog.csdn.net/fancylovejava/article/details/44747759

三、自定義imageview,使用Movie來播放

好了,對於這個,我親手做了個demo,註解還算全
由於是要自定義控制元件,我們還可能會用到一些自定義的屬性,因此在values目錄下新建一個attrs.xml的檔案,可以在這個檔案中新增任何需要自定義的屬性。這裡我們目前只需要一個auto_play屬性,程式碼如下所示:
<declare-styleable name="MyImageView">
        <attr name="auto_play" format="boolean">

        </attr>
    </declare-styleable>

這個寫好了,接下來我們要寫一個類來繼承imageview或view

package com.jp.tools;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Movie;
import android.os.SystemClock;
import android.util.AttributeSet;
import
android.util.Log; import android.util.TypedValue; import android.view.View; import android.widget.ImageView; import com.jp.activity.R; import java.io.InputStream; import java.lang.reflect.Field; /** * Created by Administrator on 2015/8/21. */ public class MyImageView extends ImageView implements View.OnClickListener { /** * 播放GIF動畫的關鍵類 */ private Movie mMovie; /** * 控制播放的按鈕 */ private Bitmap mStartButton; /** * 記錄動畫開始的時間 */ private long mMovieStart; /** * GIF圖片的寬度 */ private int mImageWidth; /** * GIF圖片的高度 */ private int mImageHeight; /** * 圖片是否正在播放 */ private boolean isPlaying; /** * 是否允許自動播放 */ private boolean isAutoPlay; public MyImageView(Context context) { super(context); Log.e("ten", "72"); } public MyImageView(Context context, AttributeSet attrs) { this(context, attrs, 0); Log.e("ten", "73"); } public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setImageResLoad(context, attrs, defStyleAttr); } private void setImageResLoad(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyImageView); Log.e("ten", "1 "); int resourceID = getResourcesID(typedArray); typedArray.recycle(); if (resourceID != 0) { Log.e("ten", "2 "); InputStream inputStream = getResources().openRawResource(resourceID); //對圖片進行解碼 mMovie = Movie.decodeStream(inputStream); if (mMovie != null) { Log.e("ten", "3 "); // 如果返回值不等於null,就說明這是一個GIF圖片,下面獲取是否自動播放的屬性 isAutoPlay = typedArray.getBoolean(R.styleable.MyImageView_auto_play, false); Bitmap bitmap = BitmapFactory.decodeStream(inputStream); mImageWidth = bitmap.getWidth(); mImageHeight = bitmap.getHeight(); bitmap.recycle(); if (!isAutoPlay) { // 當不允許自動播放的時候,得到開始播放按鈕的圖片,並註冊點選事件 mStartButton = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); setOnClickListener(this); } } } } /** * 通過Java反射,獲取src指定圖片資源所對應的id。 */ public int getResourcesID(TypedArray typedArray) { Log.e("ten", "4 "); try { Field field = TypedArray.class.getDeclaredField("mValue"); field.setAccessible(true); TypedValue typedValueObject = (TypedValue) field.get(typedArray); return typedValueObject.resourceId; } catch (Exception e) { e.printStackTrace(); } finally { if (typedArray != null) { typedArray.recycle(); } } return 0; } @Override public void onClick(View v) { Log.e("ten", "5 "); if (v.getId() == getId()) { //點選圖片開始播放 isPlaying = true; invalidate(); } } @Override protected void onDraw(Canvas canvas) { Log.e("ten", "6"); if (mMovie == null) { Log.e("ten", "7b"); // mMovie等於null,說明是張普通的圖片,則直接呼叫父類的onDraw()方法 super.onDraw(canvas); } else { Log.e("ten", "7c"); //如果mMovie不等於null,那就說明是gif圖片 if (isAutoPlay) { Log.e("ten", "7d"); //如果允許播放,呼叫palyMovie(); playMovie(canvas); invalidate(); } else { Log.e("ten", "7e"); //不允許自動播放,判斷是否要播放 if (isPlaying) { if (playMovie(canvas)) { isPlaying = false; Log.e("ten", "7f"); } invalidate(); } else { // 還沒開始播放就只繪製GIF圖片的第一幀,並繪製一個開始按鈕 Log.e("ten", "g"); mMovie.setTime(0); mMovie.draw(canvas, 0, 0); int imageX = (mImageWidth - mStartButton.getWidth()) / 2; int imageY = (mImageHeight - mStartButton.getHeight()) / 2; canvas.drawBitmap(mStartButton, imageX, imageY, null); } } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.e("ten", "onMeasure_1"); if (mMovie != null) { Log.e("ten", "onMeasure_2"); // 如果是GIF圖片則重寫設定myImageView的大小 setMeasuredDimension(mImageWidth, mImageHeight); } } /** * 開始播放GIF動畫,播放完成返回true,未完成返回false。 * * @param canvas * @return 播放完成返回true,未完成返回false。 */ public boolean playMovie(Canvas canvas) { Log.e("ten", "playMovie_1"); long now = SystemClock.uptimeMillis(); if (mMovieStart == 0) { mMovieStart = now; } int duration = mMovie.duration(); if (duration == 0) { duration = 1000; } int loadTime = (int) ((now - mMovieStart) % duration); mMovie.setTime(loadTime); mMovie.draw(canvas, 0, 0); if ((now - mMovieStart) >= duration) { mMovieStart = 0; return true; } return false; } }

佈局的程式碼:

<com.jp.tools.MyImageView

        android:src="@drawable/pic_four"
        android:layout_width="match_parent"
        android:layout_height="match_parent"

        attr:auto_play="true"
        />
    <!--設定attr:auto_play="true"動態圖就會自動播放,如果不設定,或未false圖片就需要點了之後才播放 -->

效果圖(哈哈,還是很萌的妹紙吧):
這裡寫圖片描述
對了,還有一點需要說一下,這種方法的實現當gif圖片過大的時候會報oom。所以對於圖片的大小要注意一下。

希望大家多多交流,有什麼更好的實現方法