Селектор 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 52

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));

работает нормально с изменениями ниже.

static {
 AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

добавлено в класс приложения.
сборка приложений.gradle внутри defaultConfig

vectorDrawables.useSupportLibrary = true