You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Glide加载远程SVG丢失背景颜色的修复方案咨询

Glide加载SVG丢失背景颜色的问题

问题描述

使用Glide加载远程SVG资源时,SVG背景颜色丢失,但在Chrome浏览器显示正常。

正常显示效果:
正常显示

Glide加载后的异常效果:
异常显示

(注:为让白色文字可见,自行设置了黑色背景)

相关代码及SVG地址:

Glide.with(this)
    .`as`(PictureDrawable::class.java)
    .listener(SvgSoftwareLayerSetter())
    .load("https://api.edns.domains/metadata/0x53a0018f919bde9C254bda697966C5f448ffDDcB/30610703517456202125772346661883251373457451536551224931705160096554106665587/image.svg")
    .into(binding.iv1)
public class SvgDecoder implements ResourceDecoder<InputStream, SVG> {

  @Override
  public boolean handles(@NonNull InputStream source, @NonNull Options options) {
    return true;
  }

  public Resource<SVG> decode(
      @NonNull InputStream source, int width, int height, @NonNull Options options)
      throws IOException {
    try {
      SVG svg = SVG.getFromInputStream(source);
      return new SimpleResource<>(svg);
    } catch (SVGParseException ex) {
      throw new IOException("Cannot load SVG from stream", ex);
    }
  }
}
public class SvgDrawableTranscoder implements ResourceTranscoder<SVG, PictureDrawable> {
    @Nullable
    @Override
    public Resource<PictureDrawable> transcode(@NonNull Resource<SVG> toTranscode, @NonNull Options options) {
        SVG svg = toTranscode.get();
        Picture picture = svg.renderToPicture();
        PictureDrawable drawable = new PictureDrawable(picture);
        return new SimpleResource<>(drawable);
    }
}
@GlideModule
public class SvgModule extends AppGlideModule {
  @Override
  public void registerComponents(
      @NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
    registry
        .register(SVG.class, PictureDrawable.class, new SvgDrawableTranscoder())
        .append(InputStream.class, SVG.class, new SvgDecoder());
  }

  @Override
  public boolean isManifestParsingEnabled() {
    return false;
  }
}
public class SvgSoftwareLayerSetter implements RequestListener<PictureDrawable> {

    @Override
    public boolean onLoadFailed(GlideException e, Object model, Target<PictureDrawable> target, boolean isFirstResource) {
        ImageView view = ((ImageViewTarget<?>) target).getView();
        view.setLayerType(ImageView.LAYER_TYPE_NONE, null);
        return false;
    }

    @Override
    public boolean onResourceReady(PictureDrawable resource, Object model, Target<PictureDrawable> target, DataSource dataSource, boolean isFirstResource) {
        ImageView view = ((ImageViewTarget<?>) target).getView();
        view.setLayerType(ImageView.LAYER_TYPE_SOFTWARE, null);
        return false;
    }
}

解决方案

原因分析

当前的SvgDrawableTranscoder仅渲染了SVG的矢量图形,但Android的PictureDrawable不会自动解析并应用SVG的背景色属性,导致背景丢失。

修复方案1:修改Transcoder添加背景色处理

修改SvgDrawableTranscoder,提取SVG根节点的背景色并设置到PictureDrawable上:

public class SvgDrawableTranscoder implements ResourceTranscoder<SVG, PictureDrawable> {
    @Nullable
    @Override
    public Resource<PictureDrawable> transcode(@NonNull Resource<SVG> toTranscode, @NonNull Options options) {
        SVG svg = toTranscode.get();
        Picture picture = svg.renderToPicture();
        PictureDrawable drawable = new PictureDrawable(picture);
        
        // 提取SVG根节点的背景色
        Element root = svg.getDocument().getDocumentElement();
        String styleAttr = root.getAttribute("style");
        if (styleAttr != null && styleAttr.contains("background-color")) {
            // 解析颜色值
            String colorValue = styleAttr.split(":")[1].replace(";", "").trim();
            try {
                int color = Color.parseColor(colorValue);
                drawable.setColorFilter(new PorterDuffColorFilter(color, PorterDuff.Mode.SRC_OVER));
            } catch (IllegalArgumentException ignored) {}
        }
        
        return new SimpleResource<>(drawable);
    }
}

修复方案2:解析SVG时插入背景层

如果背景色定义在SVG内部元素而非根节点,可在SvgDecoder中手动添加背景矩形:

public class SvgDecoder implements ResourceDecoder<InputStream, SVG> {

  @Override
  public boolean handles(@NonNull InputStream source, @NonNull Options options) {
    return true;
  }

  public Resource<SVG> decode(
      @NonNull InputStream source, int width, int height, @NonNull Options options)
      throws IOException {
    try {
      SVG svg = SVG.getFromInputStream(source);
      Document doc = svg.getDocument();
      Element svgRoot = doc.getDocumentElement();
      
      // 获取SVG视口尺寸
      float viewWidth = svg.getDocumentViewBox().getWidth();
      float viewHeight = svg.getDocumentViewBox().getHeight();
      
      // 创建白色背景矩形(可替换为SVG实际背景色)
      Element bgRect = doc.createElementNS("http://www.w3.org/2000/svg", "rect");
      bgRect.setAttribute("x", "0");
      bgRect.setAttribute("y", "0");
      bgRect.setAttribute("width", String.valueOf(viewWidth));
      bgRect.setAttribute("height", String.valueOf(viewHeight));
      bgRect.setAttribute("fill", "#ffffff");
      
      // 插入到SVG最底层
      svgRoot.insertBefore(bgRect, svgRoot.getFirstChild());
      
      return new SimpleResource<>(svg);
    } catch (SVGParseException ex) {
      throw new IOException("Cannot load SVG from stream", ex);
    }
  }
}

修复方案3:使用Glide官方SVG扩展库

最简便的方式是使用Glide官方维护的SVG扩展,它已处理所有兼容性问题:

  1. 添加依赖到build.gradle:
implementation 'com.github.bumptech.glide:svg:4.16.0'
  1. 删除自定义的SvgDecoder、SvgDrawableTranscoder、SvgModule和SvgSoftwareLayerSetter,直接简化加载代码:
Glide.with(this)
    .load("https://api.edns.domains/metadata/0x53a0018f919bde9C254bda697966C5f448ffDDcB/30610703517456202125772346661883251373457451536551224931705160096554106665587/image.svg")
    .into(binding.iv1)

这样就能正常显示SVG的背景色了。


内容的提问来源于stack exchange,提问作者dwh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 16:44:57