Векторная графика в списке слоев на более старых версиях Android

На новых версиях Android следующий код:

<?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> 

Производит это безупречно .

Однако более ранние версии Android (API 16 и 19, из того, что я тестировал) вообще не нравятся, и я получаю

 E/AndroidRuntime: FATAL EXCEPTION: main Process: package.app, PID: 11490 android.view.InflateException: Binary XML file line #26: Error inflating class ImageView 

При инфляции. Я использовал app:srcCompat для всех моих ImageViews, поэтому проблем там нет.

Стандартные векторные чертежи также отлично работают, но при размещении в layer-list они вызывают хаос. Есть ли обходные пути?

Solutions Collecting From Web of "Векторная графика в списке слоев на более старых версиях Android"

Атрибуты width / height для вектора, который можно вынести в вашем списке слоев, поддерживаются только в API 23 (Marshmallow) и выше. Если вы посмотрите на свой список слоев, который можно извлечь в редакторе Android Studio, эти атрибуты должны иметь желтые блоки вокруг них, а также предупреждение о том, что это не будет надежно работать на старых устройствах.

Но я думаю, что вы можете избавиться от предупреждения и добиться такого же центрирующего эффекта, как это:

 <?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> 

Я тестировал это на старом телефоне с интерфейсом API 15, и он работал нормально. Надеюсь, это сработает и для вас.

Этот ответ опирается на статью AppCompat – Age of the Vectors Криса Банеса (который работает в Библиотеке поддержки). По этому вопросу мы смотрим конкретно на раздел под названием «Волшебный» способ .

Повреждение, которое вы испытываете, связано с тем, что библиотека поддержки позволяет использовать некоторые способы использования VectorDrawables по умолчанию, а список слоев не является одним из них.

Существует специальный блок кода, который вы можете добавить в начало своей деятельности, чтобы включить использование другого VectorDrawable например <layer-list> :

 static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); } 

Примечание: связанная статья содержит опечатку в этом имени метода, используя «FromSources», она должна быть «FromResources», как показано выше.

Вам нужно будет добавить это к каждой операции, где вы хотите использовать такие чертежи, или, возможно, включить ее в класс BaseActivity, из которого распространяются другие ваши действия.

В этой статье это должно означать следующее:

DrawableContainers, которые ссылаются на другие ресурсы drawables, которые содержат только векторный ресурс.

… StateListDrawable … InsetDrawable, LayerDrawable, LevelListDrawable и RotateDrawable.

Следует отметить, однако, этот метод сильно сочетается со словом «май», это может работать , и оно не включено по умолчанию, поэтому будьте в курсе и убедитесь, что он действительно работает для вас!

Теперь есть еще одно измерение этого вопроса, кредит другим пользователям Селиму Аджими и Рапунцелю Ван Винкле для решения этого вопроса в их ответах. <layer-list> имеет другое поведение между API, в частности атрибуты width и height вашего <item> которые поддерживаются только в API 23+. Это не является причиной вашего сбоя, и это не приведет к сбою вашего приложения, но будет означать, что ваш образ не будет выглядеть так, как только вы его используете в предыдущих API.

Предложение от Rapunzel Van Winkle действительно кажется хорошим способом правильно позиционировать правильно API API (проверено на API 16 и 24):

 <?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> 
 <?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item android:drawable="@[package:]drawable/drawable_resource" android:id="@[+][package:]id/resource_name" android:top="dimension" android:right="dimension" android:bottom="dimension" android:left="dimension" /> </layer-list> 

Как вы можете видеть, здесь нет атрибутов width / height …

Вы можете добавить битмап к элементу Я думаю, что это лучшее решение

Поддержка VectorDrawble на старых версиях Android весьма ограничена , если вы используете vectorDrawables.useSupportLibrary = true :

Вы можете использовать VectorDrawableCompat для API уровня 7 и AnimatedVectorDrawableCompat на всех устройствах под управлением Android 5.0 (уровень API 11) и выше. Как Android загружает чертежи, а не каждое место, которое принимает идентификатор с возможностью рисования, например, в файле XML, поддерживает загрузку векторных чертежей. В пакете android.support.v7.appcompat добавлен ряд функций, облегчающих использование векторных чертежей. Во-первых, когда вы используете пакет android.support.v7.appcompat с ImageView или с такими подклассами, как ImageButton и FloatingActionButton, вы можете использовать новое приложение: атрибут srcCompat для ссылок на векторные чертежи, а также любые другие доступные для Android возможности: src

Даже в коде вы ограничены:

Чтобы изменить чертежи во время выполнения, вы можете использовать метод setImageResource (), как и раньше. Использование AppCompat и приложения: srcCompat – самый надежный способ интеграции векторных чертежей в ваше приложение.

Что ты можешь сделать?

Мало возможных решений:

  1. Есть альтернативный вариант для VectorDrawable, который вы используете в LayerDrawable. Поместите его в res / drawable-xxhdpi, например, и VectorDrawable в res / drawable-anydpi.

  2. Не используйте vectorDrawables.useSupportLibrary = true пока у вас есть приложение minSdk, способное использовать VectorDrawable. Это будет работать, потому что IDE будет генерировать PNG-файлы для вас.

  3. Создайте layerList программно (пример здесь ), и для того, чтобы поместить VectorDrawable, используйте AppCompatResources.getDrawable . Вы также можете сделать это с помощью XML, за исключением части размещения VectorDrawable.

Кстати, причина, по которой это ограничено, заключается в том, что Google не смог сделать ее эффективной и без проблем. Вы можете получить первоначальную попытку получить полную поддержку, используя AppCompatDelegate.setCompatVectorFromResourcesEnabled (true), но, как говорят документы, вы рискуете здесь :

Эта функция по умолчанию отключена, так как включение ее может вызвать проблемы с использованием памяти и проблемы с обновлением экземпляров Configuration. Если вы обновите конфигурацию вручную, вы, вероятно, не захотите включить это. Вы были предупреждены .