Android學習之ImageView放置gif動態圖
阿新 • • 發佈:2019-02-13
最近做圖片的時候碰到一個問題,就是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。所以對於圖片的大小要注意一下。
希望大家多多交流,有什麼更好的實現方法