Android Fresco Load SVG/Vector Drawable

Jul 11, 2019

If you try to load vector/SVG

draweeView.setImageURI(UriUtil.getUriForResourceId(R.drawable.sample_vector))// orval 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)
simpleDraweeView.setImageResource(R.drawable.ic_add_black_24dp)

NOTE: DraweeView.setImageDrawable and DraweeView.setImageResource are Deprecated.

If you are using URI, refer to Android Fresco Load Vector Drawable From Uri.

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.

❤️ Is this article helpful?

Buy me a coffee ☕ or support my work via PayPal to keep this space 🖖 and ad-free.

Do send some 💖 to @d_luaz or share this article.

✨ By Desmond Lua

A dream boy who enjoys making apps, travelling and making youtube videos. Follow me on @d_luaz

👶 Apps I built

Travelopy - discover travel places in Malaysia, Singapore, Taiwan, Japan.