Подтвердить что ты не робот

Использование андроидных векторных ловушек при преломлении 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. Используя эту косвенную ссылку, вы можете использовать векторные элементы рисования в таких случаях, как атрибут TextViews android: drawableLeft, который обычно не может поддерживать векторные элементы рисования.

Когда я использую 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
4b9b3361

Ответ 1

ПОСЛЕДНИЕ ОБНОВЛЕНИЯ - июнь /2019

Поддержка библиотеки немного изменилась с момента первоначального ответа. Теперь даже Gradle может автоматически генерировать PNG во время сборки. Итак, ниже приведены два новых подхода, которые должны работать в эти дни. Вы можете найти больше информации здесь:

Библиотека поддержки

Вероятно, это решение, которое будет работать для вас. Если вы пришли сюда, это означает, что ваша Android Studio не генерирует PNG автоматически для вас.. Итак, ваше приложение падает. Генерация PNG поддерживает только подмножество элементов XML. Это решение, однако, поддерживает все теги XML. Итак, у вас есть полная поддержка вашего вектора.

Сначала вы должны обновить свой билд сборки для его поддержки:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

dependencies {
  compile 'com.android.support:appcompat-v7:23.2.0' // OR HIGHER
}

А затем используйте app:srcCompat вместо android:src для векторных рисунков. Не забывай это.

Для TextView, если вы используете AndroidX, вы можете использовать app:drawableLeftCompat (или right, top, bottom) вместо app:drawableLeft

Если вы не используете AndroidX или кнопку, вы можете попробовать установить динамически через

Drawable icon = AppCompatResources.getDrawable(context, <drawable_id>);
textView.setCompoundDrawablesWithIntrinsicBounds(<leftIcon>,<topIcon>,<rightIcon>,<bottomIcon>);

ПНГ Поколение

Gradle может автоматически создавать изображения PNG для вас во время сборки. Однако в этом подходе поддерживаются не все элементы xml. Это решение удобно, потому что вам не нужно ничего менять в своем коде или в build.gradle. Просто убедитесь, что вы используете плагин Android 1.5.0 или выше и Android Studio 2.2 или выше.

Я использую это решение в моем приложении и работает нормально. Дополнительный флаг build.gradle не требуется. Никаких взломов не требуется. Если вы перейдете в "/build/generate/res/pngs/...", вы увидите все сгенерированные PNG.

Итак, если у вас есть простой значок (так как не все элементы XML поддерживаются), это решение может работать для вас. Просто обновите вашу Android Studio и плагин Android Gradle.


ОБНОВЛЕНИЕ - июль /2016

Они снова включили этот VectorDrawable в
Библиотека поддержки Android 23.4.0

Для пользователей AppCompat мы добавили opt-in API для повторного включения поддержки Vector Drawables из ресурсов (поведение, приведенное в 23.2) через AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) - имейте в виду, что это все еще может вызывать проблемы с использованием памяти и проблемы обновления Экземпляры конфигурации, следовательно, почему это отключено по умолчанию.

Возможно, настройка build.gradle устарела, и вам просто нужно включить его в надлежащих действиях (однако, нужно протестировать).

Теперь, чтобы включить его, вы должны сделать:

public class MainActivity extends AppCompatActivity {
    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

    ...
}

Оригинальный ответ - апрель /2016

Я думаю, что это происходит, потому что Вектор поддержки был отключен в последней версии библиотеки: 23.3.0

Согласно этому посту:

Для пользователей AppCompat мы решили удалить функциональность, которая позволяет использовать векторные рисунки из ресурсов на устройствах до Lollipop из-за проблем, обнаруженных в реализации в версии 23.2.0/23.2.1 (ISSUE 205236). Использование app: srcCompat и setImageResource() продолжает работать.

Если вы посещаете выпуск ISSUE 205236, кажется, что они будут включены в будущем, но проблема с памятью не будет решена в ближайшее время:

В следующем выпуске я добавил opt-in API, где вы можете снова включить поддержку VectorDrawable, которая была удалена. Это идет с теми же предостережениями, что и раньше (использование памяти и проблемы с обновлением конфигурации).

У меня была похожая проблема. Таким образом, в моем случае я снова вернул все значки, которые используют векторное рисование из ресурса, в изображения в формате PNG (поскольку проблема с памятью будет происходить даже после того, как они предоставят возможность включить ее снова).

Я не уверен, что это лучший вариант, но, по моему мнению, он исправляет все сбои.

Ответ 2

У меня такая же проблема. Но, занимаясь исследованиями и разработками, я получил ответ.

Для использования 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", чтобы получить отрисовку.

Ответ 4

Ответ от Guillherme P довольно удивительный. Просто для того, чтобы сделать небольшое улучшение, вам не нужно добавлять эту строку в каждое действие, если вы добавили ее один раз в класс Application, она также будет работать.

public class App extends Application {

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

ПОМНИТЕ: Вам все еще нужно включить использование библиотеки поддержки в gradle:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Кроме того, убедитесь, что вы используете версию библиотеки поддержки, более позднюю, чем v23.4, когда Google вернул поддержку Drawable Containers для VectorDrawables (примечание к выпуску)

Обновить

И для изменения кода:

  1. Обязательно обновляйте app:srcCompat каждом месте, которое принимает атрибут android:src (среда IDE предупредит вас, если он недопустим, как для <bitmap>).
  2. Для атрибутов 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);
    }
    

Ответ 5

У меня была та же проблема. И исправить это, удалив

vectorDrawables.useSupportLibrary = true

Моя целевая версия - 25, а поддержка -

 compile 'com.android.support:appcompat-v7:25.3.1'

Ответ 6

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 или аналогичного.

Ответ 7

Много НИОКР, наконец, получим это решение для сбоев на устройствах перед леденцом на палочке.

Для просмотра изображений

  • используйте приложение: 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

Ответ 8

Для тех, кто обновляется до версии Android 3.0 и выше, нет необходимости использовать AppCompatDelegate.setCompatVectorFromResourcesEnabled(true) или устанавливать vectorDrawables.useSupportLibrary = true (добавьте, что это вызовет проблему) и использовать app:srcCompat, это просто работает.

У меня уйдет два дня, чтобы понять это, и я не могу найти никаких связанных документов в Google Docs...

Ответ 9

Я использую VectorDrawables на устройствах Pre-lollipop, и вот как я это делаю: -

Шаг 1: Поместите это на уровне вашего приложения gradle.

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Шаг 2:

Поместите это в свой класс приложения и не забудьте зарегистрировать свой класс приложения в файле манифеста.

public class App extends Application {
    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }
}

Шаг 3:

Получить VectorDrawables с помощью

imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));

Ответ 10

Просто наложите вектор, отображаемый в список состояний, и проблема будет решена.

Например, у вас есть стрелка назад векторное изображение:

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. Если вы не перекрываете их, это не удастся.

Ответ 11

Самый простой способ использования:

  app:drawableRightCompat ="@drawable/ic_mobilelogin"
  app:drawableEndCompat="@drawable/ic_mobilelogin"
app:srcCompat="@drawable/ic_mobile"

и... просто используйте приложение: ** Compat для совместимости

Также добавьте поддержку build.gradle (Модуль)

android {
 defaultConfig {
vectorDrawables.useSupportLibrary = true
               }
        }

Ответ 12

AppCompatTextView теперь поддерживает app:drawableLeftCompat, app:drawableTopCompat, app:drawableRightCompat, app:drawableBottomCompat, app:drawableStartCompat и app:drawableEndCompat составные рисованные объекты, поддерживающие переносимые типы рисоваемых объектов, такие как VectorDrawableCompat.

Включите это в свой файл Gradle

implementation 'androidx.appcompat:appcompat:1.1.0-alpha01'

В вашем текстовом представлении вы можете использовать

app:drawableLeftCompat
app:drawableStartCompat

Ответ 13

После использования кода ниже.

android {
  defaultConfig {
  vectorDrawables.useSupportLibrary = true  
                }
        }




public class App extends Application {
static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}}

Тем не менее, существует проблема для векторных изображений, такие атрибуты

DrawableEnd, DrawableStart, DrawableTop, DrawableBottom, Background

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

Пример:

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"
       />

Ответ 14

Предложение Guilherme P не работало для меня. Я пошел дальше и принял решение использовать png, где мне нужно делать что-то вне приложения: srcCompat, т.е. DrawableLeft, drawableRight и т.д. Это было довольно простое изменение, и оно не имеет потенциальных проблем с памятью. AppCompatDelegate.setCompatVectorFromResourcesEnabled( правда);  вводит.

Ответ 15

Альтернативой Benny's является создание суперкласса Activity:

public abstract class VectorDrawableActivity extends AppCompatActivity {
  static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
  }

  //...
}

Теперь растяните VectorDrawableActivity вместо AppCompatActivity.