Download svg image to present in Imageview of Android as?

Asked

Viewed 205 times

0

I have an api https://restcountries.eu/rest/v2/all that returns me a json on Android. This json is binded to a class using Jackson. But I need to use the url that is contained in the json that is a svg image. I want to use this image to present the image in my custom listview but I can’t convert this svg to a valid image.

I have tested several libraries like svg-android, androidsvg1.2, Glide, tested samples, tried to convert svg to png using svg2png library and nothing works, in desperation still tried to use Squared Picasso library, but obviously it would not work because the library does not have this compatibility with svg images.

I’ve been at this for more than 8 hours so I’ve been able to test almost everything that’s unnecessarily spread over the Internet... I’d really appreciate a little help!

1 answer

1


The Glide, with some adjustments and with the help of Androidsvg, supports SVG loading. You have an example in their repository which shows how. I will play the current code for posteriority:

Add appropriate dependencies (check versions):

compile 'com.github.bumptech.glide:glide:4.4.0'
compile 'com.github.bumptech.glide:annotations:4.4.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.4.0'
implementation 'com.caverock:androidsvg:1.2.1'

It is necessary to create a ResourceDecoder to convert a InputStream for SVG.

/**
 * Decodes an SVG internal representation from an {@link InputStream}.
 */
public class SvgDecoder implements ResourceDecoder<InputStream, SVG> {

  @Override
  public boolean handles(@NonNull InputStream source, @NonNull Options options) {
    // TODO: Can we tell?
    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);
    }
  }
}

A ResourceTranscoder to convert from SVG for Picture:

/**
 * Convert the {@link SVG}'s internal representation to an Android-compatible one
 * ({@link Picture}).
 */
public class SvgDrawableTranscoder implements ResourceTranscoder<SVG, PictureDrawable> {
  @Override
  public Resource<PictureDrawable> transcode(Resource<SVG> toTranscode, Options options) {
    SVG svg = toTranscode.get();
    Picture picture = svg.renderToPicture();
    PictureDrawable drawable = new PictureDrawable(picture);
    return new SimpleResource<>(drawable);
  }
}

Create a new module:

/**
 * Module for the SVG sample app.
 */
@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());
  }

  // Disable manifest parsing to avoid adding similar modules twice.
  @Override
  public boolean isManifestParsingEnabled() {
    return false;
  }
}

And a request Istener:

/**
 * Listener which updates the {@link ImageView} to be software rendered, because
 * {@link com.caverock.androidsvg.SVG SVG}/{@link android.graphics.Picture Picture} can't render on
 * a hardware backed {@link android.graphics.Canvas Canvas}.
 */
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;
  }
}

I was able to carry the flag of Brazil using the address that comes from your JSON:

Uri uri = Uri.parse("https://restcountries.eu/data/bra.svg");

GlideApp.with(this)
    .as(PictureDrawable.class)
    .listener(new SvgSoftwareLayerSetter())
    .load(uri).into(imageViewNet);

Imagem carregada

  • Thank you very much, helped, had not made the combination of both.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.