Использование векторной графики для Android при падении Lollipop
Я использую векторные рисунки в Android до Lollipop, и вот некоторые из моих библиотек и версий инструментов:
- Android Studio: 2.0
- Плагин Android Gradle: 2.0.0
- Инструменты сборки: 23.0.2
- Библиотека поддержки Android: 23.3.0
Я добавил это свойство на своем уровне приложения Build.Gradle
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Стоит также упомянуть, что я использую дополнительные элементы рисования, такие как LayerDrawable(layer_list), как указано в официальном блоге Android ( ссылка здесь), для настройки рисования для векторных рисунков за пределами app:srcCompat
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/search"/>
</level-list>
Вы найдете ссылки на векторные графические объекты вне приложения:srcCompat завершится с ошибкой до Lollipop. Однако AppCompat поддерживает загрузку векторных рисованных объектов, когда на них ссылаются в другом рисуемом контейнере, таком как StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable и RotateDrawable. Используя эту косвенную ссылку, вы можете использовать векторные объекты рисования в таких случаях, как атрибут android:drawableLeft в TextView, который обычно не может поддерживать векторные рисунки.
Когда я использую app:srcCompat
все работает нормально, но когда я использую:
android:background
android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom
на ImageView
, ImageButton
, TextView
или же EditText
до Lollipop, он бросает ожидание:
Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9
18 ответов
Я думаю, что это происходит, потому что Вектор поддержки был отключен в последней версии библиотеки: 23.3.0
Согласно этому посту:
Для пользователей AppCompat мы решили удалить функциональность, которая позволяет использовать векторные рисунки из ресурсов на устройствах, предшествующих Lollipop, из-за проблем, обнаруженных в реализации в версии 23.2.0 / 23.2.1 (ISSUE 205236). Использование app:srcCompat и setImageResource() продолжает работать.
Если вы посещаете выпуск ISSUE 205236, кажется, что они будут включены в будущем, но проблема с памятью не будет решена в ближайшее время:
В следующем выпуске я добавил opt-in API, где вы можете снова включить поддержку VectorDrawable, которая была удалена. Это идет с теми же предостережениями, что и раньше (использование памяти и проблемы с обновлением конфигурации).
У меня была похожая проблема. Таким образом, в моем случае я снова вернул все иконки, которые используют векторное рисование из ресурса, в изображения PNG (поскольку проблема с памятью будет происходить даже после того, как они предоставят возможность включить ее снова).
Я не уверен, что это лучший вариант, но, по моему мнению, он исправляет все сбои.
ОБНОВИТЬ
Они снова включили этот VectorDrawable в
Библиотека поддержки Android 23.4.0
Для пользователей AppCompat мы добавили opt-in API для повторного включения поддержки VectorDrawable s из ресурсов (поведение, описанное в 23.2) через AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) - имейте в виду, что это все еще может вызывать проблемы с использованием памяти и проблемы с обновлением экземпляров конфигурации, поэтому по умолчанию он отключен.
Может быть build.gradle
настройка теперь устарела, и вам просто нужно включить ее в надлежащих действиях (однако, нужно проверить).
Теперь, чтобы включить его, вы должны сделать:
public class MainActivity extends AppCompatActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
...
}
У меня такая же проблема. Но, занимаясь исследованиями и разработками, я получил ответ.
Для использования Imageview и ImageButton app:srcCompat="@drawable/...." и для других представлений, таких как Button, Textview, вместо использования drawableLeft/right..."в XML, программно задайте drawables как:
button.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(mContext,R.drawable.ic_share_brown_18dp), null, null, null);
И используйте "AppCompatResources", чтобы получить отрисовку.
Чтобы уточнить другие очень хорошие ответы, вот схема, которая может вам помочь. Это допустимо, если у вас есть библиотека поддержки с 23.4.0 по крайней мере 25.1.0.
Ответ от Guillherme P довольно удивительный. Просто для того, чтобы сделать небольшое улучшение, вам не нужно добавлять эту строку в каждое действие, если вы добавили ее один раз в класс Application, она также будет работать.
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
ПОМНИТЕ: Вам все еще нужно включить использование библиотеки поддержки в gradle:
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Кроме того, убедитесь, что вы используете версию библиотеки поддержки больше, чем v23.4, когда Google вернул поддержку Drawable Containers для VectorDrawables ( примечание к выпуску)
Обновить
И для изменения кода:
- Не забудьте обновить до
app:srcCompat
каждое место, которое принимаетandroid:src
атрибут (IDE предупредит вас, если он недействителен, как для<bitmap>
тег). За
drawableLeft
,drawableStart
,drawableRight
,drawableEnd
атрибуты, используемые вTextView
и аналогичные виды, вам придется установить их программно на данный момент. Пример настройкиdrawableStart
:Drawable drawable = AppCompatResources.getDrawable( getContext(), R.drawable.your_vector_drawable); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { textView.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null); }
У меня такая же проблема. И исправить это, удалив
vectorDrawables.useSupportLibrary = true
Моя целевая версия 25 и поддержка библиотеки
compile 'com.android.support:appcompat-v7:25.3.1'
VectorDrawables на pre-lollipop должен нормально работать без использования
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
Если вы хотите использовать VectorDrawables внутри ImageViews, вы можете использовать атрибут srcCompat
и это будет работать, но внутри кнопок или TextViews это не будет, поэтому вам нужно обернуть Drawable в InsetDrawable или LayerDrawable. Я обнаружил еще одну хитрость: если вы используете привязку данных, вы можете сделать это:
android:drawableLeft="@{@drawable/vector_ic_access_time_24px}"
android:drawableStart="@{@drawable/vector_ic_access_time_24px}"
Это будет работать волшебным образом, я не исследовал, что происходит за кулисами, но я предполагаю, что TextView использует метод getDrawable из AppCompatResources или аналогичный.
Много НИОКР, наконец, получим это решение для сбоев на устройствах перед леденцом на палочке.
Для просмотра изображений
- используйте приложение:srcCompat вместо android:src
Для TextView/EditText
- Удалите drawableleft,drawableright.... и установите из нарисованного Java-кода.
txtview.setCompoundDrawablesWithIntrinsicBounds (AppCompatResources.getDrawable (EventDetailSinglePage.this, R.drawable.ic_done_black_24_n), null, null, null);
Для Build.gradle
vectorDrawables.useSupportLibrary = true
Самый простой способ использования:
app:drawableRightCompat ="@drawable/ic_mobilelogin"
app:drawableEndCompat="@drawable/ic_mobilelogin"
app:srcCompat="@drawable/ic_mobile"
и... просто используйте приложение:**Compat для совместимости
Также добавьте поддержку build.gradle (Модуль)
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Для тех, кто обновляет до Android Gradle 3.0 и выше, нет необходимости использовать AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
или установить vectorDrawables.useSupportLibrary = true
(добавить это вызовет проблемы) и использовать app:srcCompat
это просто работает.
У меня уйдет два дня, чтобы понять это, и я не нашел ни одной связанной документации в документации Google...
We tried 3 things
vectorDrawables.useSupportLibrary = true
Setting setCompatVectorFromResourcesEnabled in Application class
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
And use app:srcCompat
But even after that it was failing with
Resources$NotFoundException: File res/drawable/$my_icon__0.xml from color state list resource ID #0x7f080008
then we figured out that our SVG had a Gradient tag. Converting the gradient tag to individual paths for below API <= 23 and using the same SVG API >= 24 worked.
Got help from this answer /questions/6375608/teggradient-vnutri-xml-vyizyivaet-sboj-android/6375609#6375609
После использования приведенного ниже кода.
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}}
Тем не менее, проблема с векторными изображениями существует для следующих атрибутов:
DrawableEnd, DrawableStart, DrawableTop, DrawableBottom, Фон
В этом случае выполните следующие действия. Вместо того, чтобы ссылаться на векторное изображение напрямую, используйте тег селектора в качестве промежуточного файла для рисования.
Пример:
ic_warranty_icon.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="17dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="17"
android:viewportHeight="24">
<path
android:fillColor="#fff"
android:pathData="M10.927,15.589l-1.549,0.355a7.47,7.47 0,0 1,-0.878 0.056c-4.136,0 -7.5,-3.364 -7.5,-7.5s3.364,-7.5 7.5,-7.5 7.5,3.364 7.5,7.5c0,3.286 -2.126,6.078 -5.073,7.089zM8.5,2a6.508,6.508 0,0 0,-6.5 6.5c0,3.583 2.917,6.5 6.5,6.5s6.5,-2.917 6.5,-6.5 -2.917,-6.5 -6.5,-6.5z" />
safe_ic_warranty_icon.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_warranty_icon" />
</selector>
Ваш TextView/Layout.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableStart="@drawable/ic_warranty_icon"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/ic_warranty_icon"
/>
Я использую VectorDrawables на устройствах Pre-lollipop, и вот как я это делаю:
Шаг 1: Поместите это в ваш уровень приложения.
android {
defaultConfig {
vectorDrawables.useSupportLibrary = true
}
}
Шаг 2:
Поместите это в свой класс Application и не забудьте зарегистрировать свой класс Application в файле манифеста.
public class App extends Application {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
}
Шаг 3:
Получите VectorDrawables используя,
imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));
Я боролся с этим часами.
Я перепробовал все, о чем мне говорили эти ответы, но мое приложение не переставало давать сбой. Я удалил эту строку:app:srcCompat="@drawable/keyboard"
и мое приложение перестало давать сбой. а затем, когда я добавил то же самое, он снова начал вылетать. Итак, я решил открыть этот файл и увидел ошибку в первой строке:
"Раскладываемая клавиатура" не имеет декларации в базовой папке с возможностью переноса; это может привести к сбоям.
Я щелкнул правой кнопкой мыши файл и выбрал "Показать в проводнике", и он был не в папке с возможностью рисования, а в каталоге drawable-v24. Поэтому я скопировал его и вставил в каталог с возможностью рисования и, наконец, избавился от сбоев.
In my case, I was using a
TabLayout
, which I configured as it :
TabLayoutMediator(tabLayout!!, viewPager!!) { tab, position ->
if (position == 0)
tab.icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_list, theme)
else
tab.icon = ResourcesCompat.getDrawable(resources, R.drawable.ic_building_map, theme)
}.attach()
The app was crashing at line
tab.icon = ...
I change these to
tab.setIcon(R.drawable.my_vector_asset)
, as it :
TabLayoutMediator(tabLayout!!, viewPager!!) { tab, position ->
if (position == 0)
tab.setIcon(R.drawable.ic_list)
else
tab.setIcon(R.drawable.ic_building_map)
}.attach()
And it worked !
Просто наложите вектор, отображаемый в список состояний, и проблема будет решена.
Например, у вас есть стрелка назад векторное изображение:
ic_back_arrow.xml
да, вы должны наложить его на список слоев xml (ic_back_arrow_vector_vector.xml):
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/ic_back_arrow"/>
</layer-list>
Потому что логика:
vectorDrawables.useSupportLibrary = true
а также
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
не поможет вам на некоторых китайских устройствах и старых устройствах Samsung. Если вы не перекрываете их, это не удастся.
Предложение Гильерме Р не сработало для меня. Я пошел дальше и принял решение использовать png там, где мне нужно делать что-то вне приложения: srcCompat, т.е. drawableLeft, drawableRight и т. Д. Это было довольно легко изменить, и у него нет потенциальных проблем с памятью AppCompatDelegate.setCompatVectorFromResourcesEnabled(правда); вводит.
Теперь есть более простое решение, просто используйте app:drawableRightCompat из пространства имен приложения.
Или в стиле:
<style name="YourStyle">
<item name="drawableRightCompat">@drawable/your_vector</item>
</style>
Альтернативой ответу Бенни является создание Activity
суперкласс:
public abstract class VectorDrawableActivity extends AppCompatActivity {
static {
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
//...
}
Теперь продлим VectorDrawableActivity
вместо AppCompatActivity
,