Використання андроїд векторних малюнків на попередньо аварії льодяник


91

Я використовую векторні малюнки в 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 (список_слоїв), як зазначено в офіційному блозі 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до льодяника, він кидає expection:

Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9


Щоб побачити, як використовувати VectorDrawable з
drawableLeft, drawableRight, drawableTop, drawableBottom

Ви можете перевірити мою відповідь тут? stackoverflow.com/a/40523623/2557258
Yazon2006

У моєму випадку вакторні малюнки не були в правильному пакеті (відкритий перегляд проекту) оригінальна відповідь тут stackoverflow.com/a/35836318/2163045
murt

Відповіді:


102

ОСТАННЄ ОНОВЛЕННЯ - червень / 2019

Бібліотека підтримки дещо змінилася з часу оригінальної відповіді. Тепер навіть плагін Android для Gradle здатний автоматично генерувати PNG під час збірки. Отже, нижче наведено два нових підходи, які повинні працювати сьогодні. Ви можете знайти більше інформації тут:

Покоління PNG

Gradle може автоматично створювати зображення PNG із ваших ресурсів під час побудови. Однак у цьому підході підтримуються не всі елементи xml . Це рішення зручне тим, що вам не потрібно нічого змінювати в коді або в build.gradle. Просто переконайтеся, що ви використовуєте Android Plugin 1.5.0 або вище та Android Studio 2.2 або новішу версію .

Я використовую це рішення в своєму додатку і чудово працює. Не потрібно додатковий прапор build.gradle . Хакери не потрібні. Якщо ви перейдете до / build / generated / res / pngs / ..., ви зможете побачити всі створені PNG-файли.

Отже, якщо у вас є якась проста піктограма (оскільки підтримуються не всі елементи xml), це рішення може підійти вам. Просто оновіть Android Studio та плагін Android для Gradle.

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

Можливо, це рішення, яке підійде саме вам. Якщо ви прийшли сюди, це означає, що ваша Android Studio не генерує PNG автоматично. Отже, ваш додаток аварійно завершує роботу.

Або, можливо, ви не хочете, щоб Android Studio взагалі генерувала PNG.

На відміну від "генерації авто-PNG", яке підтримує підмножину елемента XML, це рішення підтримує всі теги xml. Отже, ви маєте повну підтримку для вашого малюваного вектора.

Спочатку потрібно оновити build.gradle, щоб підтримати його:

android {
  defaultConfig {
    // This flag will also prevents Android Studio from generating PNGs automatically
    vectorDrawables.useSupportLibrary = true
  }
}

dependencies {
  // Use this for Support Library
  implementation 'com.android.support:appcompat-v7:23.2.0' // OR HIGHER

  // Use this for AndroidX
  implementation 'androidx.appcompat:appcompat:1.1.0' // OR HIGHER
}

А потім використовуйте app:srcCompatзамість android:srcзавантаження VectorDrawables. Не забувайте про це.

Для TextView, якщо ви використовуєте androidxверсію бібліотеки підтримки, ви можете використовувати app:drawableLeftCompat(або праворуч, зверху, знизу) замістьapp:drawableLeft

У випадку CheckBox/ RadioButton, використовуйте app:buttonCompatзамість android:button.

Якщо ви не використовуєте androidxверсію бібліотеки підтримки, а ваша версія minSdkVersionє 17або новіша, або використовуєте кнопку, ви можете спробувати встановити програмно за допомогою

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

ОНОВЛЕННЯ - липень / 2016

Вони знову включили VectorDrawable в
бібліотеці підтримки Android 23.4.0

Для користувачів AppCompat , ми додали неавтоматичного в API , щоб повторно включити підтримку Vector від ресурсів вводиться коефіцієнта (поведінка знаходиться в 23.2) через AppCompatDelegate.setCompatVectorFromResourcesEnabled (істина) - мати на увазі , що це по- , як і раніше може викликати проблеми з використанням пам'яті і проблеми з оновленням екземплярів конфігурації, отже, чому він вимкнений за замовчуванням.

Можливо , build.gradleналаштування вже застаріло, і вам просто потрібно ввімкнути його у належних діях (однак, потрібно протестувати).

Тепер, щоб увімкнути його, потрібно зробити:

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

    ...
}

Оригінальна відповідь - квітень / 2016

Я думаю, що це відбувається, оскільки службу підтримки Vector було вимкнено в останній бібліотечній версії: 23.3.0

Відповідно до цього POST :

Для користувачів AppCompat ми вирішили видалити функціональність, яка дозволяє використовувати векторні малюнки з ресурсів на пристроях до льодяника через проблеми, виявлені у реалізації у версії 23.2.0 / 23.2.1 (ВИПУСК 205236) . Використання програми: srcCompat та setImageResource () продовжує працювати.

Якщо ви відвідаєте випуск ISSUE 205236 , схоже, вони ввімкнуться в майбутньому, але проблема з пам'яттю не буде вирішена найближчим часом:

У наступному випуску я додав API для вибору, де ви можете знову ввімкнути підтримку VectorDrawable, яку було видалено. Він поставляється з тими самими застереженнями, що і раніше (використання пам'яті та проблеми з оновленням конфігурації).

У мене була подібна проблема. Отже, у моєму випадку я знову повернув усі піктограми, які використовують вектор, який можна малювати з ресурсу, до зображень у форматі PNG (оскільки проблема з пам’яттю буде продовжуватися навіть після того, як вони нададуть можливість її повторного ввімкнення).

Я не впевнений, що це найкращий варіант, але він виправляє всі збої, на мій погляд.


1
Дякую @Guilherme P., але чому ви не видалили vectorDrawables.useSupportLibrary = trueвластивість, щоб повернутися до увімкнення генерації png під час збірки ?
Бехзад Бахманяр,

1
Це було вимкнено в останній версії v23.3.0 через проблеми з пам'яттю. Таким чином, вони не можуть генерувати png під час виконання ... Ось чому в помилці logcat вони друкують: невідомий вектор тегу (або щось подібне).
W0rmH0le

4
Ось інструкції щодо входу plus.google.com/+AndroidDevelopers/posts/B7QhFkWZ6YX . На жаль, VectorDrawables все ще не працює на пристрої Pre-Lollipop. Я працюю в бібліотеці підтримки 23.4.0 і маю як 'generatedDensities = []', так і 'vectorDrawables.useSupportLibrary = true', викликані в defaultConfig {}.
Адам Гурвіц,

1
@AdamHurwitz Я оновив відповідь .. Здається, її знову було ввімкнено .. Однак зараз потрібно ввімкнути її по-іншому.
W0rmH0le

1
@juztcode Ви маєте рацію. Ви повинні використовувати 'androidx.appcompat: appcompat: 1.1.0'
W0rmH0le

63

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

Для використання Imageview та ImageButton, app:srcCompat="@drawable/...." а також для інших подань, таких як Button, Textview, замість використання "drawableLeft/right..."в XML, програмно вкажіть малюнки як:

button.setCompoundDrawablesWithIntrinsicBounds(AppCompatResources.getDrawable(mContext,R.drawable.ic_share_brown_18dp), null, null, null);

І використовуйте "AppCompatResources", щоб отримати можливість малювання.


59

Щоб детальніше розглянути інші дуже добрі відповіді , ось схема, яка може вам допомогти. Це дійсно, якщо у вас є бібліотека підтримки з 23.4.0 до принаймні 25.1.0.

Шпаргалка VectorDrawable


1
у випадку, якщо ви намагаєтесь встановити drawableLeft, оберніть його всередині drawable, як згадано тут medium.com/@chrisbanes/…
nizam.sp

Дякую, ця діаграма нам дуже допомогла.
silentsudo

39

Відповідь від Guillherme P досить приголомшлива. Просто щоб зробити невелике вдосконалення, вам не потрібно додавати цей рядок у кожну діяльність, якщо ви додали його один раз у класі Application, він також буде працювати.

public class App extends Application {

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

ПАМ’ЯТАЙТЕ: Вам все одно потрібно ввімкнути використання бібліотеки підтримки в gradle:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Крім того, переконайтеся, що ви використовуєте версію бібліотеки підтримки, перевищує v23.4, коли Google додав підтримку Drawable Containers for 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);
    }

пам’ятайте, що вам потрібно увімкнути використання бібліотеки підтримки для векторних малюнків у gradle: vectorDrawables.useSupportLibrary = true
Бенні

2
Так. Я знаю. Але існує необхідна обгортка, щоб векторні малюнки працювали як малюнки для TexViews, тому ця відповідь є неповною.
цезард

1
Чудова відповідь. Це особливо добре для додатків, усі дії яких поширюються на спеціальну базову діяльність.
Гонг

14

У мене була та сама проблема. І виправити, видаливши

vectorDrawables.useSupportLibrary = true

Моя цільова версія - 25, а бібліотека підтримки -

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

1
це спрацювало для мене. Дякую. Я щойно видалив цеvectorDrawables.useSupportLibrary = true
Android Посередній

Я думаю, що це не належний спосіб це зробити, я в будь-якому випадку відмовився від вашої відповіді. !!
Харіш Редді

Дякую. t працює для мого додатка. Усі векторні малюнки все ще працюють, якщо їх було видалено. Додаток використовує com.android.support:appcompat-v7:28.0.0
Гонг

10

VectorDrawables на попередньому льодянику повинні працювати нормально без використання

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

Якщо ви хочете використовувати VectorDrawables всередині ImageViews, ви можете використовувати атрибут, srcCompatі він буде працювати, але всередині Buttons або TextViews це не буде , тому вам потрібно обернути Drawable у InsetDrawable або LayerDrawable. Є ще одна хитрість, яку я виявив: якщо ви використовуєте прив'язку даних, ви можете зробити це:

android:drawableLeft="@{@drawable/vector_ic_access_time_24px}"
android:drawableStart="@{@drawable/vector_ic_access_time_24px}"

Це чарівно спрацює, я не досліджував, що відбувається за лаштунками, але, мабуть, TextView використовує метод getDrawable з AppCompatResources чи подібного.


Як встановити векторне зображення в селекторі?
Тушар Гогна

після встановлення vectorDrawables.useSupportLibrary = true у gradle за замовчуванням і AppCompatDelegate.setCompatVectorFromResourcesEnabled (true); у процесі створення Щоб уникнути збою з android: drawableleft у Textview , встановіть drawble ліворуч до textview програмістично для examplel: textview.setCompoundDrawablesWithIntrinsicBounds (R.drawable.movie, 0, 0, 0);
Афжалур Рахман Рана

7

Багато досліджень та розробок, нарешті, отримали це рішення для збоїв на пристроях, що передують льодяник.

Для Imageview

  • використовувати app: 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 = істина


1
Це було унікальне рішення, яке працювало над TextInputEditText.
heronsanches

1
Awsome, це вирішило мою проблему. Це слід прийняти відповідь.
DJtiwari

6

Найпростіший спосіб використання:

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

і ... просто використовуйте app:**Compatдля сумісності. Також додайте підтримку на build.gradle(модуль)

android {
   defaultConfig {
       vectorDrawables.useSupportLibrary = true
   }
}

app: drawableEndCompat та app: drawableRightCompat - це майже те саме, якщо його англійська
Hossam Hassan

5

Для тих, хто переходить на android gradle 3.0 і вище, немає необхідності використовувати AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)або встановлювати vectorDrawables.useSupportLibrary = true(додайте це спричинить проблему) та використовувати app:srcCompat, це просто працює.

Візьміть мені два дні, щоб це зрозуміти, і не знайдіть жодних пов’язаних документів у документах Google ...


Цікаво, що я використовую gradle 3.3.0, і це рішення працює. Однак Android Studio все ще каже мені, щоб увімкнути set vectorDrawables.useSupportLibrary = true.
masterwok

2

Я використовую VectorDrawables на пристроях перед льодяником, і ось як я це роблю: -

Крок 1: Помістіть це у свій додаток gradle.

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

2

Після використання наведеного нижче коду.

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 / макет.

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

Дякую !!! Для фонової властивості додавання селектора між ними, а не безпосереднє використання векторного малювального файлу, працювало для api перед льодяником (19).
Анкур

у моєму випадку це все одно не працює для API (16), навіть обгортанняselector
mochadwi

1

Ми спробували 3 речі

vectorDrawables.useSupportLibrary = true

Налаштування setCompatVectorFromResourcesEnabled у класі Application

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

І використовувати app:srcCompat

Але навіть після цього це не вдалося

Resources$NotFoundException: File res/drawable/$my_icon__0.xml from color state list resource ID #0x7f080008

тоді ми з’ясували, що наш SVG мав тег Gradient. Перетворення градієнтного тегу на окремі шляхи для нижче API <= 23 та використання того самого SVG API> = 24 спрацювало.

Отримав допомогу від цієї відповіді https://stackoverflow.com/a/47783962/2171513


Не знаю, чому ніхто не голосує за це, але насправді це може бути рішенням моєї проблеми. Дякую
DevMike01

0

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

Наприклад, у вас є векторне зображення зі стрілкою назад:

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. Якщо ви не перекриєте їх, це не вдасться.


0

Я боровся з цим годинами.

Я спробував усе, що наказали мені ці відповіді, але мій додаток не припиняв збій. Я видалив цей рядок: app:srcCompat="@drawable/keyboard"і мій додаток припинив збій. а потім, коли я додав цю саму річ назад, вона знову почала падати. Тому я вирішив відкрити цей файл, і в першому рядку я побачив помилку

Msgstr "" Клавіатура ", яку можна малювати, не містить декларації в базовій папці, яку можна малювати; це може призвести до збоїв.

Я клацнув правою кнопкою миші файл і натиснув "Показати в провіднику", і він знаходився не в папці, що малюється, а в каталозі drawable-v24. Тож я скопіював його та вставив у каталог, який можна малювати, і нарешті позбувся збоїв.


-2

Пропозиція Гільерме П. мені не спрацювала. Я продовжив і прийняв рішення використовувати png там, де мені потрібно робити речі поза додатком: srcCompat, тобто drawableLeft, drawableRight тощо. Це було досить легко зробити, і у нього немає потенційних проблем з пам'яттю AppCompatDelegate.setCompatVectorFromResourcesEnabled ( правда); вводить.


-3

Альтернативою відповіді Бенні є створення Activityсуперкласу:

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

  //...
}

Тепер продовжте VectorDrawableActivityзамість AppCompatActivity.


@cesards Чому ні?
Code-Apprentice
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.