On newer Android versions, the following code:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#bdbdbd" />
<size
android:width="60dp"
android:height="60dp" />
</shape>
</item>
<item
android:drawable="@drawable/ic_library_books_black_24dp"
android:gravity="center"
android:width="40dp"
android:height="40dp"
>
</item>
</layer-list>
produces this flawlessly:
However, earlier Android versions (API 16 and 19, from what I've tested) do not like this at all and I get
E/AndroidRuntime: FATAL EXCEPTION: main
Process: package.app, PID: 11490
android.view.InflateException: Binary XML file line #26: Error inflating class ImageView
upon inflation. I have used app:srcCompat
for all my ImageViews so there is no problem there.
Standard Vector Drawables also work fine, but when placed in a layer-list
they cause mayhem. Are there any workarounds?
The width/height attributes for the vector drawable in your layer-list are only supported in API 23 (Marshmallow) and higher. If you look at your layer-list drawable in the Android Studio editor, these attributes should have yellow blocks around them along with a warning that this won't work reliably on older devices.
But I think you can get rid of the warning and achieve the same centering effect like this:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="oval">
<solid android:color="#bdbdbd" />
<size
android:width="60dp"
android:height="60dp" />
</shape>
</item>
<item
android:drawable="@drawable/ic_library_books_black_24dp"
android:top="10dp"
android:bottom="10dp"
android:left="10dp"
android:right="10dp">
</item>
</layer-list>
I tested this on an old API 15 phone and it worked fine. I hope this works for you too.
In a previous version of this answer, I'd advised against using vectorDrawables.useSupportLibrary = true
with layer lists, because it caused crashes. However, I've recently learned about a workaround that seems to fix the crash (while avoiding the fat auto-generated png files that @android developer correctly mentioned). Here's a summary of what needs to be done for it to work correctly:
Be sure to use srcCompat in your xml.
<android.support.v7.widget.AppCompatImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/layer_list_with_svg" />
Add 'vectorDrawables.useSupportLibrary' to app/build.gradle
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Add 'setCompatVectorFromResourcesEnabled(true)' to onCreate
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
setContentView(R.layout.activity_main);
}
As a more knowledgable person explained it to me, this has to do with how Android loads up the compat vector drawables. If you're using vectorDrawables.useSupportLibrary = true
then image views will load up VectorDrawableCompat
drawables when you use app:srcCompat
. When your layer list drawable is inflated, there's no way for it to figure out how to create those referenced vector drawables. But if you turn on setCompatVectorFromResourcesEnabled
it will try to hook the vector drawable loading in at a much lower level than image views and their app:srcCompat
attribute, so it's then able to figure out how to load the vector drawables referenced in the layer list.