在自定义View的onDraw方法中绘制可播放GIF作为底层背景
自定义View底层绘制GIF背景的靠谱方案
别用废弃的Movie类了,换Glide处理GIF帧
Movie类早就被官方废弃,高版本Android里根本找不到对应依赖,直接用Glide库来解码和播放GIF帧就行,步骤如下:
1. 先加Glide依赖
在模块级的build.gradle里的dependencies块中添加:
implementation 'com.github.bumptech.glide:glide:4.16.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
2. 自定义View的具体实现
写一个继承自View的类,用Glide加载GIF,拿到可动画的Drawable,然后在onDraw里先画GIF背景,再画其他内容:
public class GifBackgroundView extends View { private AnimatedDrawable2 gifDrawable; private boolean gifLoaded = false; public GifBackgroundView(Context context) { super(context); loadGif(); } public GifBackgroundView(Context context, AttributeSet attrs) { super(context, attrs); loadGif(); } private void loadGif() { // 这里加载assets里的GIF,也可以换成res里的资源ID或者网络链接 Glide.with(this) .asDrawable() .load("file:///android_asset/your_bg.gif") .addListener(new RequestListener<Drawable>() { @Override public boolean onLoadFailed(GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) { return false; } @Override public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) { if (resource instanceof AnimatedDrawable2) { gifDrawable = (AnimatedDrawable2) resource; // 设置动画循环播放 gifDrawable.registerAnimationCallback(new AnimatedDrawable2.AnimationCallback() { @Override public void onAnimationEnd(AnimatedDrawable2 drawable) { drawable.start(); } }); gifLoaded = true; invalidate(); } return false; } }) .submit(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 先画GIF背景,确保在最底层 if (gifLoaded && gifDrawable != null) { gifDrawable.setBounds(0, 0, getWidth(), getHeight()); gifDrawable.draw(canvas); // 动画运行时,请求下一帧重绘 if (gifDrawable.isRunning()) { postInvalidateOnAnimation(); } } // 这里写你要画的上层内容,比如文字、图形 Paint textPaint = new Paint(); textPaint.setColor(Color.WHITE); textPaint.setTextSize(60f); textPaint.setTextAlign(Paint.Align.CENTER); canvas.drawText("我是上层内容", getWidth()/2f, getHeight()/2f, textPaint); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); // 页面显示时启动动画 if (gifDrawable != null) { gifDrawable.start(); } } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); // 页面销毁时停止动画,避免内存泄漏 if (gifDrawable != null) { gifDrawable.stop(); } } }
3. 要注意的几个点
- 把你的GIF放在正确的位置,比如assets文件夹,或者用
R.drawable.your_gif作为加载路径 - 一定要先画GIF,再画其他内容,这样GIF才会在底层
- 在View绑定和解绑窗口时启停动画,防止内存浪费
之前崩溃的大概率原因
你之前按SO方案崩溃,多半是这几个问题:
- 用了废弃的Movie类,高版本Android不兼容
- GIF资源路径写错,导致空指针
- 没处理好动画帧的重绘,把UI线程搞崩了
用上面Glide的方案就能避开这些坑,因为Glide已经帮你做好了各版本的适配。
内容的提问来源于stack exchange,提问作者Rishabh Gupta
相关产品推荐
相关产品推荐

