前段时间做了个项目,有播放gif的需求,
而android展示gif的时候只是播放其第一帧.
主要原理呢,就是通过movie来播放gif的每一帧。

相关代码如下:

package com.em.widget;import java.io.InputStream;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;import android.widget.ImageView;import com.em.R;public class Fsgifview extends ImageView {/** * 默认为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 Fsgifview(Context context) {this(context, null);}public Fsgifview(Context context, AttributeSet attrs) {this(context, attrs, R.styleable.FSGifViewStyle_drawablevalue);}public Fsgifview(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.FSGifViewStyle, defStyle, 0);mMovieResourceId = array.getResourceId(R.styleable.FSGifViewStyle_drawablevalue, -1);array.recycle();if (mMovieResourceId != -1) {//根据设置的gif资源文件获取到moive对象mMovie = Movie.decodeStream(getResources().openRawResource(mMovieResourceId));}}/** * 设置gif图资源 *  * @param movieResId */public void setMovieResource(int movieResId) {}@Overridepublic void setImageResource(int resId) {this.mMovieResourceId = resId;InputStream is = getResources().openRawResource(mMovieResourceId);mMovie = Movie.decodeStream(is);//重写setimageResource方法,获取到赋值及时通知播放requestLayout();}public void setMovie(Movie movie) {this.mMovie = movie;requestLayout();}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;// }// invalidate();// }/** * 判断gif图是否停止了 *  * @return */// public boolean isPaused() {// return this.mPaused;// }@Overrideprotected 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());}}@Overrideprotected 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;}@Overrideprotected void onDraw(Canvas canvas) {if (mMovie != null) {// if (!mPaused) {updateAnimationTime();drawMovieFrame(canvas);invalidateView();// } else {// drawMovieFrame(canvas);// }}}@SuppressLint("NewApi")private void invalidateView() {if (mVisible) {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {postInvalidateOnAnimation();} else {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();}@SuppressLint("NewApi")@Overridepublic void onScreenStateChanged(int screenState) {super.onScreenStateChanged(screenState);mVisible = screenState == SCREEN_STATE_ON;invalidateView();}@SuppressLint("NewApi")@Overrideprotected void onVisibilityChanged(View changedView, int visibility) {super.onVisibilityChanged(changedView, visibility);mVisible = visibility == View.VISIBLE;invalidateView();}@Overrideprotected void onWindowVisibilityChanged(int visibility) {super.onWindowVisibilityChanged(visibility);mVisible = visibility == View.VISIBLE;invalidateView();}}



attr 属性文件中的配置,可以通过这个来获取到gif图像的值,用于decodestream播放gif
    <declare-styleable name="FSGifViewStyle">        <attr name="drawablevalue" format="reference" />    </declare-styleable>





更多相关文章

  1. 在Android中通过Java修改文件权限
  2. Android开发便签9:在android资源文件中定义字符串数组
  3. java/android 统计文件夹大小及删除文件夹下所有文件和路径
  4. Android:使用SAX或者DOM或者pull操作XML文件
  5. android系统中运行jar文件
  6. Android frameworks添加资源后编译报错:找不到添加的内部资源 com
  7. 使用android MediaPlayer播放音频文件时,有时会出现prepareasync
  8. Android Studio NDK及so文件开发 以及常见错误

随机推荐

  1. Android(安卓)Studio下运行开源项目9GAG
  2. 处女男学Android(三)---Handler简介以及初
  3. Android图片内存优化-Android(安卓)8.0上
  4. 实时改变配置
  5. 为Android应用程序读取/dev下设备而提权(
  6. Android多渠道打包相关介绍
  7. Android手机软件汉化教程---第五课 打包
  8. android 2.0发布
  9. 经典Android(安卓)人脸识别案例解析
  10. Android游戏开发一些心得(多个SurfaceView