zoukankan      html  css  js  c++  java
  • Glide只播放一次Gif以及监听播放完成的实现方案

    需求:

    近段时间正好有一个需求,是要实现Gif图只加载播放一次,并且要在Gif播放完毕后回调给系统的需求。

    因为Glide 3系列的API与4系列还是有很大差距的,这里我们针对Glide 3.x和Glide 4.x的分别进行实现方案的说明。

    解决方案:

    在Glide3.x的解决方案:

    Glide.with(this).load("xxxurl")
                    .listener(new RequestListener<Integer, GlideDrawable>() {
    
                        @Override
                        public boolean onException(Exception arg0, Integer arg1,
                                Target<GlideDrawable> arg2, boolean arg3) {
                            return false;
                        }
    
                        @Override
                        public boolean onResourceReady(GlideDrawable resource,
                                Integer model, Target<GlideDrawable> target,
                                boolean isFromMemoryCache, boolean isFirstResource) {
                            // 计算动画时长
                            GifDrawable drawable = (GifDrawable) resource;
                            GifDecoder decoder = drawable.getDecoder();
                            for (int i = 0; i < drawable.getFrameCount(); i++) {
                                duration += decoder.getDelay(i);
                            }
                            //发送延时消息,通知动画结束
                            handler.sendEmptyMessageDelayed(MESSAGE_SUCCESS,
                                    duration);
                            return false;
                        }
                    }) //仅仅加载一次gif动画
                    .into(new GlideDrawableImageViewTarget(imageview, 1));

    在Glide3.x的解决方案:

    在Glide4.x中,我们没法再直接获取GifDecoder对象了,原因是因为GlideDrawable不再提供这个方法了。需要采用反射的方法获取到GifDecoder变量,具体代码如下:

    public static void loadOneTimeGif(Context context, Object model, final ImageView imageView, final GifListener gifListener) {
            Glide.with(context).asGif().load(model).listener(new RequestListener<GifDrawable>() {
                @Override
                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<GifDrawable> target, boolean isFirstResource) {
                    return false;
                }
    
                @Override
                public boolean onResourceReady(GifDrawable resource, Object model, Target<GifDrawable> target, DataSource dataSource, boolean isFirstResource) {
                    try {
                        Field gifStateField = GifDrawable.class.getDeclaredField("state");
                        gifStateField.setAccessible(true);
                        Class gifStateClass = Class.forName("com.bumptech.glide.load.resource.gif.GifDrawable$GifState");
                        Field gifFrameLoaderField = gifStateClass.getDeclaredField("frameLoader");
                        gifFrameLoaderField.setAccessible(true);
                        Class gifFrameLoaderClass = Class.forName("com.bumptech.glide.load.resource.gif.GifFrameLoader");
                        Field gifDecoderField = gifFrameLoaderClass.getDeclaredField("gifDecoder");
                        gifDecoderField.setAccessible(true);
                        Class gifDecoderClass = Class.forName("com.bumptech.glide.gifdecoder.GifDecoder");
                        Object gifDecoder = gifDecoderField.get(gifFrameLoaderField.get(gifStateField.get(resource)));
                        Method getDelayMethod = gifDecoderClass.getDeclaredMethod("getDelay", int.class);
                        getDelayMethod.setAccessible(true);
                        //设置只播放一次
                        resource.setLoopCount(1);
                        //获得总帧数
                        int count = resource.getFrameCount();
                        int delay = 0;
                        for (int i = 0; i < count; i++) {
                            //计算每一帧所需要的时间进行累加
                            delay += (int) getDelayMethod.invoke(gifDecoder, i);
                        }
                        imageView.postDelayed(new Runnable() {
                            @Override
                            public void run() {
                                if (gifListener != null) {
                                    gifListener.gifPlayComplete();
                                }
                            }
                        }, delay);
                    } catch (NoSuchFieldException e) {
                        e.printStackTrace();
                    }catch (ClassNotFoundException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                    return false;
                }
            }).into(imageView);
        }
    
        /**
         * Gif播放完毕回调
         */
        public interface GifListener {
            void gifPlayComplete();
        }

    同时,因为采用的是反射,所以别忘了proguard-rules.pro中加上Glide的反混淆规则:

    #Glide
    -keep class com.bumptech.glide.** {*;}
  • 相关阅读:
    登录模块(前端bookstrapValidator校验+加密+后台加密+后台验证)
    spring+springmvc+mybatis+redis 实现两重数据缓存
    spring+springmvc+mybatis+redis实现缓存
    获取网页上的所有QQ号码,并生成exel报表
    单点登录(因为原理一样,所以没有实现注销)
    solr 基本命令二(权重查找)
    solr 搭建 (基于solr-5.0.0)
    OC 添加导航栏item
    xcode 一些三方库版本警告 iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.2.99.
    Swift UITextView设置富文本点击, 取消一切点击事件(放大镜/复制粘贴/删除等等)
  • 原文地址:https://www.cnblogs.com/renhui/p/11936962.html
Copyright © 2011-2022 走看看