Search code examples
androiddrawableandroid-vectordrawable

Vector Drawables in Layer List on Android API 16 and higher


I am having some trouble with vectors drawable on older API version in Android. I need to change drawables at runtime each time the activity starts should load the corresponding svg file.

This is my layer list :

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item >
    <shape android:shape="oval">
        <size android:height="50dp" android:width="50dp"/>
        <!-- fill color -->
        <solid android:color="@color/white" />
    </shape>
</item>
<item
    android:id="@+id/avatar"
    android:drawable="@drawable/dog" //I need to change this at run time
    android:bottom="10dp"
    android:left="10dp"
    android:right="10dp"
    android:top="10dp"/>

In my activity, I am using

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

So far I am using layer drawable to pick the xml file and change the svg but I am having compatibility issues as layerDrawable.setDrawble() is only available in API level >= 23

 layerDrawable = (LayerDrawable) ContextCompat.getDrawable(this, R.drawable.seekbar_thumb);
 Drawable avatar = (Drawable) ContextCompat.getDrawable(this, getUserAvatarId());
 layerDrawable.setDrawable(0, avatar);

Solution

  • The solution of this is simple. The concept is that I wanted to change the thumb of a seek bar in the onCreate() state of an activity. The thumb of my seek bar is drawable file the one I posted. Basically, it loads an SVG file with a white stroke around it, depending on the user this SVG should be changeable.

    For Android API >= 16 the solution is the following:

    layerDrawable = (LayerDrawable) ContextCompat.getDrawable(this, R.drawable.seekbar_thumb);
    Drawable avatar = VectorDrawableCompat.create(getResources(), getUserAvatarId(), null);
    layerDrawable.mutate(); //not share its state with other drawables
    layerDrawable.setDrawableByLayerId(R.id.avatar, avatar);
    layerDrawable.invalidateSelf(); //inform the layer drawable when it needs to redraw
    seekBar.setThumb(layerDrawable);
    

    The Function setDrawableById(int, drawable) is of type boolean and returns either true if the drawable of the layer is changed or false if is not! Then you need to replace the view with the new drawable file in this case seekBar.setThumb(layerDrawable);