Селектор Android Drawable с VectorDrawables srcCompat
я столкнулся с проблемой с новой обратной совместимостью с VectorDrawables. В библиотеке поддержки 23.2 появилась новая функция обратной совместимости с Android vectordrawables indroduced.
у меня есть ImageView, который является SelectorDrawable назначен. Этот Drawable содержит несколько VectorDrawables, поэтому я подумал, что должен использовать приложение:srcCompat для совместимости. Но он не работает на моем Galaxy S2 с 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>
все чертежи являются векторными XML-файл.
при использовании этого SelectorDrawable с srcCompat я получаю эту ошибку:
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
использование android: src еще хуже.
Если я использую один из векторных чертежей с приложением: srcCompat все работает нормально. Поэтому я думаю, что это проблема с SelectorDrawable и совместимостью.
кто-нибудь имел ту же проблему и нашел решение или в настоящее время невозможно использовать VectorDrawables в SelectorDrawables до Android 5?
Быстрые Факты:
- компиляция целевого API 23
- Поддержка Libraray 23.3.0
- vectorDrawables.useSupportLibrary = true
- Gradle 2.0
4 ответа:
некоторые вещи изменились, так как я задал этот вопрос, поэтому я отвечу на него сам.
с библиотекой поддержки 23.4.0 была повторно включена поддержка VectorDrawables из Ressources:библиотека поддержки Android 23.4.0 теперь доступна
вы можете найти дополнительную информацию об этом в этом броске из Google I / O 2016: что нового в библиотеке поддержки-Google I / O 2016
вы должны добавить к любой деятельности, где вы хотите используйте VectorDrawables на устройствах ниже Android 5.0 (кодовое имя Lollipop, уровень API 21):
static { AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); }
таким образом, теперь вы можете использовать VectorDrawables в DrawableContainers, но это все еще может вызвать некоторые проблемы, как указано в источниках выше, поэтому используйте его с осторожностью.
Я не включал эту функцию в своем приложении до сих пор, но я изменю много своих значков на VectorDrawables с моим следующим крупным выпуском, а затем углублюсь в эту тему.
как @Jahnold упоминалось в комментарии к вопросу, поддержка загрузки вектора, извлекаемого из xml-списка состояния xml, была удалена в 23.3.
тем не менее, я нашел несколько подходов, которые могут помочь.
1. Используя Оттенок
подход подходит, если чертежи из выбранного списка состояний отличаются только по цветам.
во-первых, создать только один вектор drawable с оттенком и белым
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>
во-вторых, создать список состояния цвета
button_tint.xml
помещен в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>
не забудьте добавить следующие строки в
build.gradle
или этот подход не будет работать на старых версиях Android.defaultConfig { vectorDrawables.useSupportLibrary = true }
2. Создание жесткого кода
StateListDrawable
подход подходит, если вы используете для списка состояний векторные чертежи, которые отличаются не только цветом, но и фигурой, поэтому вам нужно создать несколько разных xml-файлов. Затем вы можете создать
StateListDrawable
программно, как показано в элементе ответ.
после просмотра что нового в библиотеке поддержки-Google I / O 2016 я заметил один полезный метод в
AppCompatResources
класса. ЭтоAppCompatResources#getColorStateList(Context context, int resId)
. С помощью этого метода я реализовал селектор с векторными чертежами. Вот мой файл выбора цвета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>
и есть метод java, который возвращает тонированные 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; }
вы можете использовать его, как показано ниже
yourImageView.setImageDrawable(getTintedDrawable(R.drawable.ic_vector_image));