Picasso: Support for VectorDrawables (API 21)?

Created on 12 Aug 2015  Â·  42Comments  Â·  Source: square/picasso

Is support for the new VectorDrawable type introduced in Lollipop planned as a possible enhancement?

Currently, when I attempt to load any VectorDrawable with Picasso, e.g. Picasso.with(context).load(R.drawable.ic_vector_drawable).into(imageView), the ImageView blanks out and nothing is rendered.

Most helpful comment

It would be very useful if vectors also work with the .placeholder function.
Especially now where support library 23.2 makes it possible to use vectors in pre Lollipop versions.

All 42 comments

No plans. Vectors, by definition, don't really need an image processing pipeline to change their size. Why are you wanting to use Picasso for this?

I think the use case here is for a project with mixed image asset types (i.e. PNGs and VectorDrawables). Rather than conditionally loading VectorDrawables with setImageDrawable, it would be nice to be able to use Picasso throughout the application and do something like the following, even if Picasso is just passing the VectorDrawable through:

Picasso.with(context).load(someBoolean ? R.drawable.ic_some_png : R.drawable.ic_vector_drawable).into(imageView)

This seems like it may become more common moving forward (API 21+).

I second on this feature.

Now that Android Studio supports using VectorDrawable and generates pngs for backward compatibility, you now only provide a single resource for either one. On older platforms the image loads just fine, when VectorDrawable is used Picasso fails to load it.

Now you might say put an API level check around that code, but I am using the databinding library. It does not provide any context besides the drawable resource ID. If you put an API level check around it, any image that isn't an SVG would be loaded without Picasso also.

@BindingAdapter("android:src")
public static void setSrc(ImageView view, int res) {
    // Only the resource id is provided here
    Picasso.with(view.getContext()).load(res).into(view);
}

Even a simple passthrough by Picasso would be nice.

@JakeWharton It seems the error handling code will load the vector drawable just fine after the load() call fails. I see --- SkImageDecoder::Factory returned null in the log for each image, but the vector drawable I have set is set just fine. If I remove error(), the image fails to load with the same message.

Why does the same vector drawable asset load if it's set in error(), but not load()? What is different about the error pipeline?

Picasso.with(context)
    .load(R.drawable.my_vector_drawable)
    .error(R.drawable.my_vector_drawable)
    .into(imageView);

It just calls setImageResource and delegates to Android to load.

On Tue, Dec 1, 2015, 6:20 PM Austyn Mahoney [email protected]
wrote:

@JakeWharton https://github.com/JakeWharton It seems the error handling
code will load the vector drawable just fine after the load() call fails.
I see --- SkImageDecoder::Factory returned null in the log for each
image, but the vector drawable I have set is set just fine. If I remove
error(), the image fails to load with the same message.

Why does the same vector drawable asset load if it's set in error(), but
not load()? What is different about the error pipeline?

Picasso.with(context)
.load(R.drawable.my_vector_drawable)
.error(R.drawable.my_vector_drawable)
.into(imageView);

—
Reply to this email directly or view it on GitHub
https://github.com/square/picasso/issues/1109#issuecomment-161128762.

It would be very useful if vectors also work with the .placeholder function.
Especially now where support library 23.2 makes it possible to use vectors in pre Lollipop versions.

MarcoNica:"It would be very useful if vectors also work with the .placeholder function."

+1

Applying a round transformation to an Vector Image is the thing im trying right now.

Ref articles http://android-developers.blogspot.no/2016/02/android-support-library-232.html and https://medium.com/@chrisbanes/appcompat-v23-2-age-of-the-vectors-91cbafa87c88#.741bm31xn it is possible to use Vector drawables with Picasso. You need to wrap the drawable in e.g., a StateListDrawable. Then AppCompat's magic will kick in and fetch the drawable for Picasso.

A short example. First, code for a StateListDrawable - state_list_placeholder:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:drawable="@drawable/placeholder" />
    </selector>

@drawable/placeholder obviously refers to a vector drawable asset.

Use the state list drawable with Picasso like this:

    final StateListDrawable placeholderList = (StateListDrawable) context.getResources().getDrawable(R.drawable.state_list_placeholder);
    Picasso.with(context)
                    .load(url)
                    .placeholder(placeholderList.getCurrent())
                    .resizeDimen(R.dimen.image_width, R.dimen.image_height)
                    .into(image);

The previous workaround does not work if using resource IDs because Picasso uses the Application Context (and this kind of context won't load vector drawables on 4.1). The load function does not accept drawables, only drawable IDs, so we cannot use vector drawables as the main image.

And contrary to what @JakeWharton says we may want to use Picasso with vector drawables to apply custom Bitmap transformations we already wrote for other image types.

@clemp6r that's what im talking about

Another reason for implementing this is setImageResource() loads the VectorDrawable on the UI thread, not something you really want to do. It would be nice to use Picasso to offload this to a background thread.

@austinmahoney
setImageResource needs to be called from the ui thread but the actual image loading might happen on a different thread (this is an implementation detail of AOSP).
In my experience setImageResource is very fast and non blocking.
Edit: I am proven to be wrong :)

It is definitely blocking

On Fri, Apr 15, 2016, 7:52 PM adi1133 [email protected] wrote:

@austinmahoney
setImageResource needs to be called from the ui thread but the actual
image loading might happen on a different thread (this is an implementation
detail of AOSP). In my expetience setImageResource is very fast and non
blocking.

—
You are receiving this because you were mentioned.

Reply to this email directly or view it on GitHub
https://github.com/square/picasso/issues/1109#issuecomment-210688888

@adi1133 As Jake said, straight from the setImageResource documentation:

This does Bitmap reading and decoding on the UI thread, which can cause a latency hiccup.

Profile any code that loads a VectorDrawable using setImageResource and you'll see a ton of XML String parsing. Not a great thing to do in a RecyclerView because of the massive amount of object allocation.

Here is a sample trace of what a single call to setImageResource does when you give it a VectorDrawable. This is all happening on the main thread.
screen shot 2016-04-15 at 7 09 00 pm

I am loading VectorDrawables in RecyclerView which leads to skipping of frames. I would be great if there will be a way to move the loading into a background thread.

Actually there could be meany reasons why loading of even non-vector drawable could take some time (example: nested layer-list). So rather than focusing on vector drawables, i'd recommend a simpler implementation for the current drawable loader of picasso (which afaik only delegates to android for loading the drawable) which is completely agnostic to the type of drawable. It goes something like this:

Bitmap loadDrawable(@DrawableRes int drawableRes) {
    final Drawable drawable = ContextCompat.getDrawable(context, drawableRes);
    drawable.setBounds(0,0, drawable.intrinsicWidth, drawable.intrinsicHeight);

    final Bitmap result = Bitmap.createBitmap(intrinsicWidth, intrinsicHeight, Bitmap.Config.ARGB_8888);
    final Canvas canvas = Canvas(bitmap);
    draw(canvas)

    return bitmap
}

Of course, this doesn't have cache & error handling but shows how it could be done.
I'm using this very implementation in my app and it works fairly well

+1

In the mean time, I am trying to figure out how to disable the vector folder for anydpi-v21 by the support library in order to have all pngs.

Any ideas? The workaround by @ahaeber Didn't work for me on android 4.4.2
I need a vector drawable as a placeholder

This is a Java equivalent to the StateListDrawable solution from @ahaeber :
Tested on platform 16 and 23, with Android Compat 23.4.0 then 24.0.0

// Initialize placeholder drawable once
mPlaceholderDrawable = ResourcesCompat.getDrawable(
                                    context.getResources(), 
                                    R.drawable.vector_placeholder, null);
// Use in Picasso
Picasso.with(context)
    .load(url)
    .placeholder(mPlaceholderDrawable)

It required some extra configuration :
In gradle :

android {
    defaultConfig {
        vectorDrawables.useSupportLibrary = true

In Activity or Application :

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

References :
https://medium.com/@chrisbanes/appcompat-v23-2-age-of-the-vectors-91cbafa87c88#.crrv88967
http://android-developers.blogspot.fr/2016/02/android-support-library-232.html

You can use VectorDrawables for placeholders (and this is where VectorDrawable can be useful) on platforms that handle it natively (API 21+)

Backward compatibility is handled by both appcompat-v7 and support-v4. As Picasso by itself doesn't have a dependency with those libraries, it makes sense for me that the application has the responsibility to create a compatible Drawable for the API <20 platform and not Picasso.

Thanks for the tip @ncornette it's working. And yes I agree it's the app's responsibility to deliver the apropriate drawable but it would come in handy to just do Picasso.with(context).load(url).placeholder(R.drawable.this_is_a_vector_drawable);

Future versions of VectorDrawableCompat will reportedly handle that case,
and we will update to use it when it does.

On Tue, Jun 28, 2016 at 1:11 PM Thanos Psaridis (Fisherman) <
[email protected]> wrote:

Thanks for the tip @ncornette https://github.com/ncornette it's
working. And yes I agree it's the app's responsibility to deliver the
apropriate drawable but it would come in handy to just do
Picasso.with(context).load(url).placeholder(R.drawable.this_is_a_vector_drawable);

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/square/picasso/issues/1109#issuecomment-229116140,
or mute the thread
https://github.com/notifications/unsubscribe/AAEEEY24gAgqFUbVl3PDawi7NLbrdBoeks5qQVXBgaJpZM4FqVvJ
.

@JakeWharton Any update on this issue?

it would be very nice
is there any other option to handle svg properly in android devices ? what is going wrong with google people ?

Is it possible to use a custom svg decoder with picasso? like overriding the decoding of input stream?

@ncornette tip is not working anymore with support library v. 25.1.0 on API 25.

@JakeWharton is any way to load image by url to .svg file?
something like this:
https://example.com/link_to_vector.svg

To use vector drawables as placeholders in Picasso, load them with AppCompatResources.getDrawable(context, myVectorDrawableId) and use as normal. This method loads both bitmaps and vector drawables in a compatible way, so it'll eat anything - also on KitKat and lower.

Is there any updates? @JakeWharton

P.S. Badly missing SVG Placeholders.:(

@Kolyall Android does not have native support for SVG files period. It _does_ support a limited subset of SVG features through VectorDrawables . You will need some separate library that decodes SVG files into a supported format such as PNG, JPEG, WEBP, etc. Theoretically, you could create a RequestHandler that decodes the SVG into a Bitmap.

I looked at if it was doable without modifying Picasso and it's not pretty. My attempt is at https://gist.github.com/teslacoil/c651c4607441a60a12ed7801953536bc , but it can't work with Requests for resourceId or SCHEME_ANDROID_RESOURCE, instead the scheme has to be modified to something else.

This is due to Picasso prioritizing the default ResourceRequestHandler over anything else https://github.com/square/picasso/blob/03ce090543b504a90a5f301fb93db50255539a53/picasso/src/main/java/com/squareup/picasso/Picasso.java#L183

Would a pull request to either modify ResourceRequestHandler to be more like my gist above where if it can't load a bitmap it tries loading the drawable and drawing it to a bitmap be acceptable? Or a pull request that puts an user supplies RequestHandler above the ResourceRequestHandler if it can handle SCHEME_ANDROID_RESOURCE be acceptable?

We can modify Picasso now. The next version is 3.0.

On Thu, Jun 8, 2017, 6:10 AM Kevin notifications@github.com wrote:

I looked at if it was doable without modifying Picasso and it's not
pretty. My attempt is at
https://gist.github.com/teslacoil/c651c4607441a60a12ed7801953536bc , but
it can't work with Requests for resourceId or SCHEME_ANDROID_RESOURCE,
instead the scheme has to be modified to something else.

This is due to Picasso prioritizing the default ResourceRequestHandler
over anything else
https://github.com/square/picasso/blob/03ce090543b504a90a5f301fb93db50255539a53/picasso/src/main/java/com/squareup/picasso/Picasso.java#L183

Would a pull request to either modify ResourceRequestHandler to be more
like my gist above where if it can't load a bitmap it tries loading the
drawable and drawing it to a bitmap be acceptable? Or a pull request that
puts an user supplies RequestHandler above the ResourceRequestHandler if
it can handle SCHEME_ANDROID_RESOURCE be acceptable?

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/square/picasso/issues/1109#issuecomment-307000107,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEEEczYRbc9_17b3QGYjfyPlnahGg5rks5sB4JNgaJpZM4FqVvJ
.

Yes, this would be very handy.
https://example.com/link_to_vector.svg

Will Picasso 3.0 support this?

@prithivraj seems id of svg also should be supported
https://example.com/link_to_vector.svg#id_of_svg

In the time waiting for next 3.0 release, we can use https://bigbadaboom.github.io/androidsvg/

you need to support local files because we can use picasso in recyclerview and set for folders our local icons, and have to do it with recyclerview otherwise recyclerview won't cancel previous request and could load image into imageview which picasso should not supposed to load

simple example for loading video files' thumbnails

if you replace picasso with mImageView.setImageResource(R.drawable.ic_folder); for directories you will have problems with incorrect loading

private void bindItem(final FileItem fileItem) {

            if (fileItem.getFile().isDirectory()) {
                // if you replace picasso with mImageView.setImageResource(R.drawable.ic_folder); 
               // you will have problems with incorrect loadings
                mPicassoInstance
                        .load(R.drawable.ic_folder)
                        .placeholder(R.drawable.ic_folder)
                        .noFade()
                        .into(mImageView);
            } else {
                mPicassoInstance
                        .load("video:" + fileItem.getFile().getAbsolutePath())
                        .placeholder(R.drawable.ic_file_video)
                        .noFade()
                        .into(mImageView)
           };

Use Picasso.cancel and setImageResource.

On Fri, Mar 9, 2018 at 7:44 AM anonym24 notifications@github.com wrote:

1109 https://github.com/square/picasso/issues/1109

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/square/picasso/issues/1109#issuecomment-371802837,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAEEEUHsHuFmDAaEOGNFIzWvlZ0f5EENks5tcnk9gaJpZM4FqVvJ
.

@JakeWharton yes, thought about this myself https://github.com/square/picasso/issues/1807

Hello, are you planning to release the support for xml drawables in a stable version soon?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

apkelly picture apkelly  Â·  16Comments

christopherperry picture christopherperry  Â·  17Comments

neodroidpune picture neodroidpune  Â·  21Comments

julianonunes picture julianonunes  Â·  26Comments

pohh picture pohh  Â·  15Comments