Android Selector Drawable with VectorDrawables srcCompat

I am having a problem with new backward compatibility with VectorDrawables. Support library 23.2 had a new feature for backward compatibility with Android VectorDrawables.

I have an ImageView that is assigned a SelectorDrawable. This Drawable contains several VectorDrawables, so I decided to use the application: srcCompat for compatibility. But this does not work on my Galaxy S2 with Android 4.1.2.

<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/ic_gps_fixed_24dp"android:state_activated="true" android:state_selected="true"></item> <item android:drawable="@drawable/ic_gps_not_fixed_24dp" android:state_activated="true" android:state_selected="false"></item> <item android:drawable="@drawable/ic_gps_not_fixed_24dp" android:state_activated="false" android:state_selected="true"></item> <item android:drawable="@drawable/ic_gps_off_24dp" android:state_activated="false" android:state_selected="false"></item> <item android:drawable="@drawable/ic_gps_not_fixed_24dp"></item> </selector> 

All drawings are vector xml files.

When using this SelectorDrawable with srcCompat, I get this error:

  Caused by: android.content.res.Resources$NotFoundException: File res/drawable/ Caused by: android.content.res.Resources$NotFoundException: File res/drawable/ic_gps_fixed_24dp.xml from drawable resource ID #0x7f0201c1 at android.content.res.Resources.loadDrawable(Resources.java:1951) at android.content.res.Resources.getDrawable(Resources.java:672) at android.graphics.drawable.StateListDrawable.inflate(StateListDrawable.java:173) at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:881).xml from drawable resource ID #0x7f0201c1 

Using android: src is even worse.

If I use one of the vector drawings with the application: srcCompat everything works fine. So I think this is a problem with SelectorDrawable and compatibility.

Someone had the same problem and found a solution, or is it currently not possible to use VectorDrawables in SelectorDrawables prior to Android 5?

Brief facts:

  • Compile Target API 23
  • Support for Libraray 23.3.0
  • vectorDrawables.useSupportLibrary = true
  • Gradle 2.0
+43
android vector android-support-library android-vectordrawable appcompat-v7-r23
Apr 20 '16 at 10:29
source share
3 answers

some things have changed since I asked this question, so I’ll answer it myself.

With support for the 23.4.0 library, VectorDrawables support from Ressources has been reinstalled: Android Support Library 23.4.0 is now available

More information about this can be found in this Google I / O 2016 app: What's New in the Support Library - Google I / O 2016

You need to add this to every operation where you want to use VectorDrawables on devices running Android 5.0 (Codename Lollipop, API level 21):

 static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } 

So now you can use VectorDrawables in DrawableContainers, but it can still cause some of the problems mentioned in the sources above, so use it with caution.

I have not added this feature to my application so far, but I would change many of my icons to VectorDrawables with my next major version and then dive deeper into this topic.

+46
Jun 24 '16 at 11:53 on
source share

As @Jahnold mentioned in a comment on the question, support for loading a vector ported from an xml state xml list was removed in 23.3.

However, I found several approaches that may help.

1. Using shade

The approach is suitable if the drawings from the selected list of states differ only in colors.

First, create only one vector that you can draw with a tint and white fillColor :

 <?xml version="1.0" encoding="utf-8"?> <vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" android:viewportWidth="24" android:viewportHeight="24" android:tintMode="multiply" android:tint="@color/button_tint"> <path android:fillColor="#ffffff" android:pathData="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/> <path android:pathData="M0 0h24v24H0z"/> </vector> 

Secondly, create a list of button_tint.xml color button_tint.xml located in res/color

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="#555555" android:state_enabled="false"/> <item android:color="#6699dd"/> </selector> 

Remember to add the lines below to build.gradle or the approach will not work on older versions of Android.

 defaultConfig { vectorDrawables.useSupportLibrary = true } 

2. Creating Hard Code StateListDrawable

The approach is suitable if you use vector elements for the list, which differ not only in color but also in shape, so you need to create several different xml files. Then you can create a StateListDrawable programmatically, as shown in.

+28
Apr 27 '16 at 9:49 on
source share

After viewing What's New in the Support Library - Google I / O 2016 I noticed one useful method in the AppCompatResources class. This is AppCompatResources#getColorStateList(Context context, int resId) . Using this method, I implemented a selector with vector drawings. Here is my icon_selector color icon_selector :

 <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/red_selected" android:state_selected="true"/> <item android:color="@color/red_pressed" android:state_pressed="true"/> <item android:color="@color/red"/> </selector> 

And there is a java method that returns a tinted drawable:

  private Drawable getTintedDrawable(@DrawableRes int drawableId) { Drawable drawable; if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { drawable = getResources().getDrawable(drawableId, getTheme()); } else { drawable = getResources().getDrawable(drawableId); } drawable = DrawableCompat.wrap(drawable); DrawableCompat.setTintList(drawable.mutate(), AppCompatResources.getColorStateList(this, R.color.selector_nav_bar_item_ico)); return drawable; } 

You can use it as below.

 yourImageView.setImageDrawable(getTintedDrawable(R.drawable.ic_vector_image)); 
+4
Nov 07 '16 at 17:30
source share



All Articles