前段时间做了个项目,有播放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(安卓)登录界面Demo源码
  2. EditText android:windowSoftInputMode 属性之旅
  3. Android获取前台进程包名
  4. imageButton被边框包围的原因、解决办法
  5. android webview 设置背景透明色
  6. Android设置权限问题
  7. Android-缓存数据保存-通用方法
  8. Android幻灯片式图片浏览器
  9. 【Android】ToolBar设置NavigationIcon不显示异常或自定义失败异

随机推荐

  1. Android(安卓)自定义TextView 实现文本间
  2. 解决:Android(安卓)Android(安卓)requires
  3. Android上运行本地c
  4. Android(安卓)屏幕旋转 处理 AsyncTask
  5. Android: NDK编程入门笔记
  6. Android(安卓)Studio 模板(Template)定制
  7. 两分钟彻底让你明白Android中onIntercept
  8. android:scrollbarStyle属性及滚动条和分
  9. RelativeLayout各个属性
  10. Android四种常用布局