Android Fresco Load SVG/Vector Drawable

November 3, 2019

You could load try to load vector/SVG drawable

draweeView.setImageURI(UriUtil.getUriForResourceId(R.drawable.sample_image))

// or

val uri = Uri.parse("http://upload.wikimedia.org/wikipedia/commons/e/e8/Svg_example3.svg")
draweeView.setImageURI(uri)

But it won’t work if the drawable is vector image with the following warning.

ProgressiveDecoder: unknown image format, {uri: res:/2131230921, firstEncodedBytes: 03000800781200000100, length: 4728}

You can write your own custom decoder, where an SVG decoder example is provided.

Based on this source, Fresco support placeholder, progress bar, etc which is vector image, but only load bitmaps for the primary image.

You could load vector image into drawable

// ContextCompat.getDrawable(context, R.drawable.sample_image)
val d = AppCompatResources.getDrawable(context, R.drawable.sample_image)

But Fresco doesn’t provide a simple API to load Bitmap or Drawable into SimpleDraweeView.

The simplest solution is to use ImageView instead of SimpleDraweeView.

imageView.setImageResource(R.drawable.sample_image)

Or you could cheat by loading image as placeholder. But, what’s the point?

draweeView.hierarchy.setPlaceholderImage(R.drawable.sample_image)

Setup Fresco to load SVG

Dependencies

dependencies {
    implementation 'com.caverock:androidsvg:1.4'
}

Might need these in proguard.

-keep class com.caverock.androidsvg.** { *; }
-dontwarn com.caverock.androidsvg.**

Import SvgDecoderExample.java.

NOTE: If you are using Kotlin, you can still import the java file without the need for conversion.

Fresco setup

val imageDecoderConfig = ImageDecoderConfig.newBuilder()
            .addDecodingCapability(
                SvgDecoderExample.SVG_FORMAT,
                SvgDecoderExample.SvgFormatChecker(),
                SvgDecoderExample.SvgDecoder()
            )
            .build()

val config = ImagePipelineConfig.newBuilder(this)
    .setDownsampleEnabled(true)
    .setImageDecoderConfig(imageDecoderConfig)
    .build()

val draweeConfig = DraweeConfig.newBuilder()
    .addCustomDrawableFactory(SvgDecoderExample.SvgDrawableFactory())
    .build()

Fresco.initialize(this, config, draweeConfig)

Usage

simpleDraweeView.setImageUri(Uri.parse("https://frescolib.org/static/sample-images/fresco_logo_half_transparent.svg"))

NOTE: It won’t work for http://upload.wikimedia.org/wikipedia/commons/e/e8/Svg_example3.svg because the file start with <?xml instead of <svg. I didn’t drill further to fix this issue.

Load Vector

You can add vector asset via File -> New -> Vector Assets.

Even with Fresco SVG Decoder setup, it still cannot load vector assets.

val uri = UriUtil.getUriForResourceId(R.drawable.ic_add_black_24dp)
simpleDraweeView.setImageURI(item.uri)

NOTE: The above doesn’t work with ProgressiveDecoder: unknown image format shown in log.

The following work

val drawable = AppCompatResources.getDrawable(itemView.context, R.drawable.ic_add_black_24dp)
simpleDraweeView.setImageDrawable(drawable)

NOTE: [DraweeView.setImageDrawable](https://frescolib.org/javadoc/reference/com/facebook/drawee/view/DraweeView.html#setImageDrawable(android.graphics.drawable.Drawable) is Deprecated.

As mentioned earlier, other solutions include

  • Use ImageView instead
  • Use placeholder image: simpleDraweeView.hierarchy.setPlaceholderImage(R.drawable.ic_add_black_24dp)
  • Use Glide

NOTE: Fresco doesn’t seems to have intension to officially support Vector or SVG.

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.