1

Use in project implementation 'com.github.bumptech.glide:glide:4.8.0'

Get from server links(.svg)

How to download that .svg icon for given url and show it in ImageView with glide?

Now i use it something like this:

Glide.with(bankLogoView.context)
            .`as`(PictureDrawable::class.java)
            .load(data.logoUrl)
            .listener(SvgSoftwareLayerSetter())
            .apply(options)
            .into(bankLogoView)

Where have:

private val options = RequestOptions().centerCrop()
        .diskCacheStrategy(DiskCacheStrategy.ALL).placeholder(R.drawable.ic_logo_splash)

Also added next classes SvgDecoder:

class SvgDecoder : ResourceDecoder<InputStream, SVG> {

override fun handles(source: InputStream, options: Options): Boolean {
    // TODO: Can we tell?
    return true
}

@Throws(IOException::class)
override fun decode(source: InputStream, width: Int, height: Int,
                    options: Options): Resource<SVG>? {
    try {
        val svg = SVG.getFromInputStream(source)
        return SimpleResource(svg)
    } catch (ex: SVGParseException) {
        throw IOException("Cannot load SVG from stream", ex)
    }
}
}

SvgDrawableTranscoder:

class SvgDrawableTranscoder : ResourceTranscoder<SVG, PictureDrawable> {

override fun transcode(toTranscode: Resource<SVG>,
                       options: Options): Resource<PictureDrawable>? {
    val svg = toTranscode.get()
    val picture = svg.renderToPicture()
    val drawable = PictureDrawable(picture)
    return SimpleResource(drawable)
}
}

SvgModule:

@GlideModule
class SvgModule : AppGlideModule() {
override fun registerComponents(context: Context, glide: Glide,
                                registry: Registry) {
    registry.register(SVG::class.java, PictureDrawable::class.java, SvgDrawableTranscoder())
            .append(InputStream::class.java, SVG::class.java, SvgDecoder())
}

// Disable manifest parsing to avoid adding similar modules twice.
override fun isManifestParsingEnabled(): Boolean {
    return false
}
}

SvgSoftwareLayerSetter:

class SvgSoftwareLayerSetter : RequestListener<PictureDrawable> {

override fun onLoadFailed(e: GlideException?, model: Any, target: Target<PictureDrawable>,
                          isFirstResource: Boolean): Boolean {
    val view = (target as ImageViewTarget<*>).view
    view.setLayerType(ImageView.LAYER_TYPE_NONE, null)
    return false
}

override fun onResourceReady(resource: PictureDrawable, model: Any,
                             target: Target<PictureDrawable>, dataSource: DataSource, isFirstResource: Boolean): Boolean {
    val view = (target as ImageViewTarget<*>).view
    view.setLayerType(ImageView.LAYER_TYPE_SOFTWARE, null)
    return false
}
}

But also i display only options. data.logoUrl is not empty but doesn t display

UPD:

W/Glide: Load failed for https://mandarine.com/logos/providers/xf/fake_demobank_xf.svg with size [65x66] class com.bumptech.glide.load.engine.GlideException: Failed to load resource

Tried to hardcode some url from google when i .load("url") like a :

https://upload.wikimedia.org/wikipedia/sco/7/71/Pringles.svg

But also didn't show image.

Second way what i tried to do: Implement this library

implementation 'com.caverock:androidsvg-aar:1.3'

Then modified my layout:

<com.caverock.androidsvg.SVGImageView
        android:id="@+id/bankLogoView"
        style="@style/icon_account_view"
        app:svg="@drawable/ic_buy_violet"/>

And after in my holder smth like this:

bankLogoView.setImageAsset("wallet.svg")

but how i can download .svg file from server?

Morozov
  • 4,968
  • 6
  • 39
  • 70
  • Have you tried this? https://stackoverflow.com/questions/35507893/does-glide-have-a-method-for-loading-both-png-and-svg – davthecoder Sep 24 '18 at 13:59

2 Answers2

4

My code is in Java but hope you get the memo. Add the following dependency to your app module build.gradle file:

implementation 'com.caverock:androidsvg:1.2.1'

And in your GlideModule:

public class GlideModule 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());
    }
}

SvgDecoder.java

public class SvgDecoder implements ResourceDecoder<InputStream, SVG> {

    @Override
    public boolean handles(InputStream source, Options options) throws IOException {
        // TODO: Can we tell?
        return true;
    }

    public Resource<SVG> decode(InputStream source, int width, int height, Options options)
            throws IOException {
        try {
            SVG svg = SVG.getFromInputStream(source);
            return new SimpleResource<SVG>(svg);
        } catch (SVGParseException ex) {
            throw new IOException("Cannot load SVG from stream", ex);
        }
    }
}

SvgDrawableTranscoder.java

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<PictureDrawable>(drawable);
    }
}

SvgSoftwareLayerSetter.java

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;
    }
}

Then use it with Glide like:

Glide.with(this)
        .as(PictureDrawable.class)
        .load(svgUrl)
        .listener(new SvgSoftwareLayerSetter())
        .into(imageView);
Sdghasemi
  • 5,370
  • 1
  • 34
  • 42
  • it is not clear how to use GlideModule correctly. Where i need to use it? – Morozov Sep 24 '18 at 14:42
  • do you use it somewhere in your project? or are using only his methods? – Morozov Sep 24 '18 at 15:00
  • 1
    [Here](https://bumptech.github.io/glide/doc/configuration.html#applications) is how to configure a Glide module in your project. And about your second question, yes I use it almost every where in my app and it works like a charm. – Sdghasemi Sep 24 '18 at 15:46
  • The problem is with the annotation processor. If you read the doc in my previous comment exactly you'll notice `compile 'com.github.bumptech.glide:annotations:4.8.0' annotationProcessor 'com.github.bumptech.glide:compiler:4.8.0'` at the end of app Glide module configuration doc. – Sdghasemi Sep 24 '18 at 16:10
  • Yes, I saw this comment. and I added it to my `build.gradle`. Made rebuild project, and also get error: `There was 1 cause: java.net.UnknownHostException(Unable to resolve host "mandarine.com": No address associated with hostname) call GlideException#logRootCauses(String) for more detail` – Morozov Sep 24 '18 at 16:19
  • So the build was successful and Glide reached to the SVG load state but it didn't make it out to the server to retrieve the SVG file to process. Try to test you code against a sample SVG located in another server with another hostname and spot the culprit. – Sdghasemi Sep 24 '18 at 16:35
  • fun `onLoadFailed()` called from the class `SvgSoftwareLayerSetter` :( – Morozov Sep 25 '18 at 07:31
  • I'm currently using these dependencies for glide in my project `implementation "com.github.bumptech.glide:glide:${GLIDE_VERSION}" implementation "com.github.bumptech.glide:annotations:${GLIDE_VERSION}" api "com.github.bumptech.glide:okhttp3-integration:${GLIDE_VERSION}" annotationProcessor "com.github.bumptech.glide:compiler:${GLIDE_VERSION}"` where `${GLIDE_VERSION}` is `4.8.0`. – Sdghasemi Sep 26 '18 at 07:53
1

This does it. Starting Glide v4, decoders and transcoders don't have to be created for every request and is good to be setup once in the GlideModule. URL to InputStream is handled by Glide by one of the default ModelLoaders.

@GlideModule
class GlideModule : AppGlideModule() {
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
    registry.append( InputStream::class.java, SVG::class.java, SvgDecoder() )
    registry.register( SVG::class.java, PictureDrawable::class.java, SvgDrawableTranscoder() )
    }
}

class SvgDecoder : ResourceDecoder<InputStream, SVG> {
override fun handles(source: InputStream, options: Options): Boolean {
    return true
}

@Throws(IOException::class)
override fun decode(source: InputStream, width: Int, height: Int, options: Options): Resource<SVG> {
    try {
        val svg = SVG.getFromInputStream(source)
        return SimpleResource(svg)
    } catch (ex: SVGParseException) {
        throw IOException("Cannot load SVG from stream", ex)
    }
}
}

class SvgDrawableTranscoder : ResourceTranscoder<SVG, PictureDrawable> {
    override fun transcode(toTranscode: Resource<SVG>, options: Options): Resource<PictureDrawable> {
    val svg = toTranscode.get()
    val picture = svg.renderToPicture()
    val drawable = PictureDrawable(picture)
    return SimpleResource(drawable)
    }
}

    GlideApp.with(this)
            .load("https://sample.svg" )
            .into(imageView)
Vairavan
  • 1,246
  • 1
  • 15
  • 19