美文网首页
解决Glide4.x上的crossFade无法生效

解决Glide4.x上的crossFade无法生效

作者: ZZombiee | 来源:发表于2019-06-05 15:25 被阅读0次

    问题出现场景

    因为旧项目用的是Glide4.0,新项目升级到Glide4.8以后,加载的渐变效果crossFade在部分组件失效(RoundImageView,然而实际上在我一开始网上搜索的时候,大部分人遇到这个情况也是在这个View上)

    结果差异

    • 普通ImageView渐变效果仍然生效
    • RoundImageView以及部分自定义View失效

    CrossFade的作用过程

    glide设置图片到目标ImageView

      @Override
      public void onResourceReady(@NonNull Z resource, @Nullable Transition<? super Z> transition) {
        if (transition == null || !transition.transition(resource, this)) {
          setResourceInternal(resource);
        } else {
          maybeUpdateAnimatable(resource);
        }
      }
    

    按照上面的代码transition.transition去寻找CrossFade的代码,发现在DrawableCrossFadeTransition这个类中

      @Override
      public boolean transition(Drawable current, ViewAdapter adapter) {
        Drawable previous = adapter.getCurrentDrawable();
        if (previous == null) {
          previous = new ColorDrawable(Color.TRANSPARENT);
        }
        TransitionDrawable transitionDrawable =
            new TransitionDrawable(new Drawable[] { previous, current });
        transitionDrawable.setCrossFadeEnabled(isCrossFadeEnabled);
        transitionDrawable.startTransition(duration);
        adapter.setDrawable(transitionDrawable);
        return true;
      }
    

    乍一看,没有任何问题,构建了一个TransitionDrawable,里面有目标资源和一个透明的Drawable,ImageView在绘制的时候,会让TransitionDrawable通过切换他的两个Drawable的alpha值来达到渐变的效果

    上面说了crossFade在我的项目存在差异,系统的ImageView是生效的,自定义的则失效,Glide的源码好像又没什么问题,那问题肯定出在了自定义View上,那么就复盘自己自定义的View(以下均已RoundImageView为例)

    • 大家都知道要展示一个圆形的图片,从两方面着手,要么去处理Drawable,要么去处理View(别问为什么Glide自带处理Drawable,还要用RoundImageView,问就是自有用处)
      处理View的方法
      • canvas.clipPath
      • canvas.drawCircle+paint.setShader
      • canvas.drawBitmap+paint.setXfermode+canvas.drawCircle
    处理Drawable的方法就不谈了,因为我是在View里处理(懒~的贴),采用了上述的第二种方法

    RoundImageView里对资源的处理

    private Bitmap getBitmapFromDrawable(Drawable drawable) {
            if (drawable == null) {
                return null;
            }
            if (drawable instanceof BitmapDrawable) {
                return ((BitmapDrawable) drawable).getBitmap();
            }
            try {
                Bitmap bitmap;
                if (drawable instanceof ColorDrawable) {
                    bitmap = Bitmap.createBitmap(COLORDRAWABLE_DIMENSION, COLORDRAWABLE_DIMENSION, BITMAP_CONFIG);
                } else {
                    bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), BITMAP_CONFIG);
                }
                Canvas canvas = new Canvas(bitmap);
                drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
                drawable.draw(canvas);
                return bitmap;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }
        }
    

    获取当前的Drawable,构建一个Bitmap作为Shader来为paint着色,结合上面说的Glide返回的是一个TransitionDrawable,可知道得到的Shader获取的总是TransitionDrawable的第一个资源也就是那个透明Drawable,造成了CrossFade的失效

    查看GitHub的版本更迭


    可以看到在历史版本中,当previous为空的时候,也就是第一次设置图片的时候,其实是调用defaultAnimation.transition(current, adapter)来完成渐变的效果,这也解释了为什么我在glide4.0的时候渐变还是正常的,升级到4.8以后就部分失效的原因

    解决方案

    既然知道了Glide的版本变迁,想用回旧版本的渐变效果,只需要照猫画虎模仿就OK了

     @Override
     public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
           if (iv instanceof RoundImageView && iv.getTag(R.id.view_glide_animate) == null) {
               iv.clearAnimation();
               AlphaAnimation animation = new AlphaAnimation(0F, 1F);
               animation.setDuration(300);
               iv.startAnimation(animation);
               iv.setTag(R.id.view_glide_animate, true);
           }
          return false;
       }
    

    在Glide加载的回调中统一处理为AlphaAnimation显示渐变

    后续

    其实这个问题在网上挂了一大堆,我也查找过程也一一看了不少,都没有一个很好的解释或者良好的解决方案(也许是我查的姿势不对?),实际上只要稍微看一下源码,发现还是不难理解

    相关文章

      网友评论

          本文标题:解决Glide4.x上的crossFade无法生效

          本文链接:https://www.haomeiwen.com/subject/istsxctx.html