Android 自定义 View 播放 Gif 动画,ffmpeg 音视频开发实战 6 下载
public void setGifResource(int movieResourceId, OnPlayListener onPlayListener) {mOnPlayListener = onPlayListener;movie = Movie.decodeStream(getResources().openRawResource(movieResourceId));if (movie == null) {//如果 movie 为空,那么就不是 gif 文件,尝试转换为 bitmap 显示 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), movieResourceId);if (bitmap != null) {setImageBitmap(bitmap);return;}}movieDuration = movie.duration() == 0 ? DEFAULT_DURATION : movie.duration();requestLayout();}
调用 requestLayout 重新计算 View 大小,并重新绘制。如果是 gif 格式则 View 宽高等于 movie 的宽高,不是则调用父类的测量方法。
@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {if (movie != null) {int movieWidth = movie.width();int movieHeight = movie.height();setMeasuredDimension(movieWidth, movieHeight);} else {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}}
开始播放,其实就是调用 invalidate 从而调用 onDraw 方法就行 UI 绘制:
public void play(int counts) {this.counts = counts;reset();if (mOnPlayListener != null) {mOnPlayListener.onPlayStart();}invalidate();}
不断调用 onDraw 方法来绘制 Gif 当前时间的图片帧(同样需要判断是否是 gif 格式,不是则调用父类的绘制方法):
@Overrideprotected void onDraw(Canvas canvas) {if (movie != null) {if (!mPaused && hasStart) {drawMovieFrame(canvas);invalidateView();} else {drawMovieFrame(canvas);}} else {super.onDraw(canvas);}}/**
画出 gif 帧*/private void drawMovieFrame(Canvas canvas) {movie.setTime(getCurrentFrameTime());movie.draw(canvas, 0.0f, 0.0f);}
最核心的方法就是计算当前时间需要绘制处于 movie 中的对应时间的图片帧。
private int getCurrentFrameTime() {if (movieDuration == 0)return 0;//因为有暂停,所以需要减去暂停时间 long
now = SystemClock.uptimeMillis() - dealyTime;int nowCount = (int) ((now - mMovieStart) / movieDuration);if (counts != -1 && nowCount >= counts) {hasStart = false;if (mOnPlayListener != null) {mOnPlayListener.onPlayEnd();}}int currentTime = (int) ((now - mMovieStart) % movieDuration);int percent = currentTime * 100 / movieDuration;if (mOnPlayListener != null && hasStart) {mOnPlayListener.onPlaying(percent);}return currentTime;}
暂停 Gif 播放:
public void pause() {if (movie != null && !mPaused && hasStart) {mPaused = true;invalidate();mMoviePauseTime = SystemClock.uptimeMillis();if (mOnPlayListener != null) {mOnPlayListener.onPlayPause(true);}} else {if (mOnPlayListener != null) {mOnPlayListener.onPlayPause(false);}}}
继续 Gif 播放:
if (mPaused && mMoviePauseTime > 0) {mPaused = false;dealyTime = dealyTime + SystemClock.uptimeMillis() - mMoviePauseTime;invalidate();if (mOnPlayListener != null) {mOnPlayListener.onPlayRestart();}}
经过这些处理,我们就能更好地控制 Gif 的播放流程了。下面简单看下成品图:
评论