Android ImageView播放gif圖片
阿新 • • 發佈:2018-12-22
當點選圖片的時候,gif圖片播放,當沒有點選的時候是gif的第一幀,這時是一張圖片。
參考:https://blog.csdn.net/guolin_blog/article/details/11100315
首先在values目錄下新建一個attrs.xml的檔案
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="AnimaImageView"> <attr name="auto_play" format="boolean"> </attr> </declare-styleable> </resources>
AnimaImageView繼承自ImageView,這個類支援ImageView的所有功能。
package com.example.administrator.taiyang; /** * Created by Administrator on 2018/11/4. */ 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.Build; import android.os.SystemClock; import android.util.AttributeSet; import android.util.TypedValue; import android.view.View; import android.widget.ImageView; import java.io.InputStream; import java.lang.reflect.Field; /** * @author EX_YINQINGYANG * @version [Android PABank C01, @2016-09-29] * @date 2016-09-29 * @description 可以播放gif動畫的ImageView */ public class AnimaImageView extends ImageView implements View.OnClickListener { /** * 是否自動播放 */ private boolean isAutoPlay; /** * 播放GIF動畫的關鍵類 */ private Movie mMovie; /** * gif寬高 */ private BitmapSize bitmapSize; /** * 播放按鈕 */ private Bitmap mStartBotton; /** * 是否正在播放gif */ private boolean isPlaying; /** * gif開始時間 */ private long mMovieStart; public AnimaImageView(Context context) { super(context); } public AnimaImageView(Context context, AttributeSet attrs) { this(context, attrs,0); } public AnimaImageView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { this.setLayerType(View.LAYER_TYPE_SOFTWARE,null); } obtainStyledAttr(context,attrs,defStyleAttr); } private void obtainStyledAttr(Context context, AttributeSet attrs, int defStyleAttr) { TypedArray a=context.getTheme().obtainStyledAttributes(attrs,R.styleable.AnimaImageView,defStyleAttr,0); int resId=getIdentifier(a); if(resId!=0){ // 當資源id不等於0時,就去獲取該資源的流 InputStream is=getResources().openRawResource(resId); // 使用Movie類對流進行解碼 mMovie=Movie.decodeStream(is); //mMovie不等null說明這是一個GIF圖片 if(mMovie!=null){ this.setLayerType(View.LAYER_TYPE_SOFTWARE,null); //是否自動播放 isAutoPlay=a.getBoolean(R.styleable.AnimaImageView_auto_play,false); /** * 獲取gif圖片大小 */ Bitmap bitmap= BitmapFactory.decodeStream(is); bitmapSize=new BitmapSize(bitmap.getWidth(),bitmap.getHeight()); bitmap.recycle(); if(!isAutoPlay){ // 當不允許自動播放的時候,得到開始播放按鈕的圖片,並註冊點選事件 mStartBotton=BitmapFactory.decodeResource(getResources(),R.drawable.g1); setOnClickListener(this); } } } a.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //當時gif圖片的時候,控制元件寬高為gif檔案大小 if(mMovie!=null){ setMeasuredDimension(bitmapSize.width,bitmapSize.height); } } @Override protected void onDraw(Canvas canvas) { //當為一張普通的圖片的時候 if(mMovie==null){ super.onDraw(canvas); }else{ //如果自動播放的話,就直接播放 if(isAutoPlay){ playMovie(canvas); invalidate(); }else{ //如果已經點選了播放按鈕的話就開始播放gif if(isPlaying){ if(playMovie(canvas)){ isPlaying=false; } invalidate(); }else{ // 還沒開始播放就只繪製GIF圖片的第一幀,並繪製一個開始按鈕 mMovie.setTime(0); mMovie.draw(canvas, 0, 0); int offsetW = bitmapSize.width ; int offsetH = bitmapSize.height; canvas.drawBitmap(mStartBotton, offsetW, offsetH, null); } } } } /** * 開始播放GIF動畫,播放完成返回true,未完成返回false。 * * @param canvas * @return 播放完成返回true,未完成返回false。 */ private boolean playMovie(Canvas canvas) { //獲取當前時間 long now = SystemClock.uptimeMillis(); if (mMovieStart == 0) { mMovieStart = now; } int duration = mMovie.duration(); if (duration == 0) { duration = 1000; } int relTime = (int) ((now - mMovieStart) % duration); mMovie.setTime(relTime);//不斷的設定gif的播放位置 mMovie.draw(canvas, 0, 0);//將movie畫在canvas上 //如果(當前時間-gif開始的時間=gif總時長)說明播放完畢了 if ((now - mMovieStart) >= duration) { mMovieStart = 0; return true; } return false; } /** * 通過反射獲取src中的資源id * @param a */ private int getIdentifier(TypedArray a) { try { Field mValueFiled = a.getClass().getDeclaredField("mValue"); mValueFiled.setAccessible(true); TypedValue typedValue= (TypedValue) mValueFiled.get(a); return typedValue.resourceId; } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return 0; } /** * 當點選圖片的時候播放gif */ @Override public void onClick(View v) { isPlaying = true; invalidate(); } /** * BitmapSize */ class BitmapSize{ private int width; private int height; public BitmapSize(int width, int height) { this.width = width; this.height = height; } } }
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:attr="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" > <com.example.administrator.taiyang.AnimaImageView android:layerType="software" android:layout_width="wrap_content" android:layout_height="wrap_content" attr:auto_play="false" android:src="@drawable/g1" android:layout_weight= "1"/> </RelativeLayout>
這裡要注意包名:<com.example.administrator.taiyang.AnimaImageView
attr:auto_play="false" 是禁止fig動畫自動播放。
可改為 attr:auto_play="true" 自動播放。
有些4.0以上系統的手機啟動了硬體加速功能之後會導致GIF動畫播放不出來,因此我們需要在AndroidManifest.xml中去禁用硬體加速功能。
AndroidManifest.xml,在<application 下增加
android:hardwareAccelerated="false"
android:largeHeap="true"
如果src屬性裡面指定的是一張PNG圖片,圖片在佈局正中央也會顯示出來,正是普通ImageView所具備的功能。