安卓里的gif图片解决方案:Fresco+gif

背景

gif图片的特殊性

安卓里常用的图片有jpg,png,webp,gif.前三者都是位图模式,而gif实际上是几张图片依次播放的动画.

安卓原生并不支持gif的显示.

Fresco图片加载框架能够显示gif动画,但是有几个坑.

fresco 显示gif的基本方法:开启自动播放就可以了

  PipelineDraweeController controller =
            (PipelineDraweeController) Fresco.newDraweeControllerBuilder()
                    .setImageRequest(request)
                    .setControllerListener(listener)
                    .setOldController(draweeView.getController())
                    .setAutoPlayAnimations(true) //自动播放gif动画
                    .build();



    draweeView.setController(controller);

    //或者,不显式地构建imagerequest:
     public static void setSupportGif(SimpleDraweeView draweeView,String url){

        PipelineDraweeController controller =(PipelineDraweeController) Fresco.newDraweeControllerBuilder()
                        .setUri(url)
                        .setOldController(draweeView.getController())
                        .setAutoPlayAnimations(true) //自动播放gif动画
                        .build();
        draweeView.setController(controller);
    }

 gif圆角和圆形:圆角与动画不可兼得

fresco里设置圆角可使用以下两种方式:

  1. 默认使用一个 shader绘制圆角,但是仅仅占位图和所要显示的图有圆角效果。失败示意图和重下载示意图无圆角效果,且这种圆角方式不支持动画。
  2. 叠加一个solid color来绘制圆角。但是背景需要固定成指定的颜色。 在XML中指定 roundWithOverlayColor,或者通过调用setOverlayColor来完成此设定。很多时候,xml里设置没有效果,要代码中进行设定.

很显然,gif动画要显示圆角,是要通过第二种方式,盖一层圆角颜色,其实颜色下方,图像还是长方形的。圆角状态下,动画是不会动的,即使开启了自动播放.

通过BaseBitmapDataSubscriber获取bitmap时,如果图像是gif,那么虽然回调是success,但返回的bitmap为null。那么,如何让gif格式时返回的bitmap为第一帧的图像?

解决的思路是:
在成功的回调里,去拿到已经缓存的gif文件,对其进行解码,然后拿到第一帧的bitmap。
如果对bitmap大小有要求,那么可以在解码时就指定生成的图片大小,获取拿到第一帧后再压缩。两者对比肯定第二种省内存。
当然,最好是服务器能直接将gif转换成jpg返回。

  /**
 * 拿到指定宽高,并经过Processor处理的bitmap
 * @param url
 * @param context
 * @param width
 * @param height
 * @param processor 后处理器,可为null
 * @param listener
 *
 */
public static void getBitmapWithProcessor(@NonNull final String url,@NonNull  Context context,@NonNull final int width,@NonNull final int height,
                                         @Nullable BasePostprocessor processor,@NonNull final BitmapListener listener){

    ResizeOptions resizeOptions = null;
    if (width !=0 && height != 0 ){
        resizeOptions = new ResizeOptions(width, height);
    }

    ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(url))
            .setProgressiveRenderingEnabled(false) //我们是拿bitmap对象,不是显示,所以这里不需要渐进渲染
            .setPostprocessor(processor)
            .setResizeOptions(resizeOptions)//无法支持gif
            .build();

    ImagePipeline imagePipeline = Fresco.getImagePipeline();

    DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, context);
    dataSource.subscribe(new BaseBitmapDataSubscriber() {
        @Override
        protected void onNewResultImpl(Bitmap bitmap) {
            //注意,gif图片解码方法与普通图片不一样,是无法拿到bitmap的。如果要把gif的第一帧的bitmap返回,怎么做?
            //GifImage.create(bytes).decode(1l,9).getFrameInfo(1).
            if (bitmap == null ){
                File cacheFile  = getFileFromDiskCache(url);
                //还要判断文件是不是gif格式的
                if ("gif".equalsIgnoreCase(getRealType(cacheFile))){//通过读取文件头的方式来判断
                        Bitmap bitmapGif = GifUtils.getBitmapFromGifFile(cacheFile);//拿到gif第一帧的bitmap
                        Bitmap target = MyBitmapUtils.compressBitmap(bitmapGif, true, width, height);//将bitmap压缩到指定宽高。
                        if (target != null) {
                            listener.onSuccess(target);
                        } else {
                            listener.onFail();
                        }
                }else {
                    listener.onFail();
                }
            }else {
                listener.onSuccess(bitmap);
            }
        }

        @Override
        protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
            listener.onFail();
        }
    }, CallerThreadExecutor.getInstance());

}

gif解析的算法有待优化,可参考:

android-gif-drawable

加载超大gif图,fresco也会及其卡顿甚至OOM:

服务器将gif图缩小后传输给客户端。比如七牛的图片处理api能够做到对gif图片的缩小尺寸以及按规定尺寸裁剪。或者干脆转成jpg。

http://developer.qiniu.com/code/v6/api/kodo-api/image/imagemogr2.html
/thumbnail/<imageSizeGeometry>
/crop/<imageSizeAndOffsetGeometry>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值