Menggunakan Drawable vektor android pada sebelum Lollipop crash

95

Saya menggunakan vector drawable di android sebelum Lollipop dan ini adalah beberapa pustaka dan versi alat saya:

  • Android Studio: 2.0
  • Plugin Android Gradle: 2.0.0
  • Alat Bangun: 23.0.2
  • Pustaka Dukungan Android: 23.3.0

Saya menambahkan properti ini di level aplikasi saya Build.Gradle

android {  
  defaultConfig {  
    vectorDrawables.useSupportLibrary = true  
   }  
}

Perlu juga disebutkan bahwa saya menggunakan drawable tambahan seperti LayerDrawable (layer_list) seperti yang dinyatakan dalam Blog resmi Android ( tautan di sini ) untuk menyetel drawable untuk vector drawable di luarapp:srcCompat

<level-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/search"/>
</level-list>

Anda akan menemukan referensi langsung vector drawable di luar app: srcCompat akan gagal sebelum Lollipop. Namun, AppCompat mendukung pemuatan vector drawable saat mereka direferensikan di container drawable lain seperti StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable, dan RotateDrawable. Dengan menggunakan indireksi ini , Anda bisa menggunakan vector drawable dalam kasus seperti atribut android: drawableLeft TextView, yang biasanya tidak dapat mendukung vector drawable.

Saat saya menggunakan app:srcCompatsemuanya berfungsi dengan baik, tetapi saat saya menggunakan:

android:background
android:drawableLeft
android:drawableRight
android:drawableTop
android:drawableBottom

pada ImageView, ImageButton, TextViewatau EditTextsebelum Lollipop, itu melempar expection:

Caused by: android.content.res.Resources$NotFoundException: File res/drawable/search_toggle.xml from drawable resource ID #0x7f0200a9
Behzad Bahmanyar
sumber
Kemungkinan duplikat kompatibilitas vektor Android
Adam Hurwitz
Untuk melihat bagaimana menggunakan VectorDrawable dengan drawableLeft, drawableRight, drawableTop, drawableBottom periksa Jawaban ini
Behzad Bahmanyar
Bisakah Anda memeriksa jawaban saya di sini? stackoverflow.com/a/40523623/2557258
Yazon2006
Dalam kasus saya, sumber daya dapat digambar vactor tidak dalam paket yang benar (tampilan proyek terbuka) jawaban asli di sini stackoverflow.com/a/35836318/2163045
murt

Jawaban:

104

PEMBARUAN TERBARU - Jun / 2019

Support Library telah sedikit berubah sejak jawaban aslinya. Sekarang, bahkan plugin Android untuk Gradle dapat secara otomatis menghasilkan PNG pada waktu pembuatan. Jadi, di bawah ini adalah dua pendekatan baru yang seharusnya berhasil saat ini. Anda dapat menemukan info lebih lanjut di sini:

Generasi PNG

Gradle dapat secara otomatis membuat gambar PNG dari aset Anda pada waktu pembuatan. Namun, dalam pendekatan ini, tidak semua elemen xml didukung . Solusi ini nyaman karena Anda tidak perlu mengubah apa pun di kode atau di build.gradle Anda. Pastikan Anda menggunakan Android Plugin 1.5.0 atau lebih tinggi dan Android Studio 2.2 atau lebih tinggi .

Saya menggunakan solusi ini di aplikasi saya dan berfungsi dengan baik. Tidak perlu flag build.gradle tambahan . Tidak perlu peretasan. Jika Anda membuka / build / generated / res / pngs / ... Anda dapat melihat semua PNG yang dihasilkan.

Jadi, jika Anda memiliki beberapa ikon sederhana (karena tidak semua elemen xml didukung), solusi ini mungkin cocok untuk Anda. Cukup perbarui Android Studio dan plugin Android Anda untuk Gradle.

Pustaka Dukungan

Mungkin, ini adalah solusi yang akan berhasil untuk Anda. Jika Anda datang ke sini, itu berarti Android Studio Anda tidak menghasilkan PNG secara otomatis. Jadi, aplikasi Anda mogok.

Atau mungkin, Anda tidak ingin Android Studio menghasilkan PNG sama sekali.

Berbeda dari "pembuatan PNG Otomatis" yang mendukung subset elemen XML, solusi ini mendukung semua tag xml. Jadi, Anda memiliki dukungan penuh untuk drawable vektor Anda.

Anda harus terlebih dahulu memperbarui build.gradle Anda untuk mendukungnya:

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
}

Dan kemudian, gunakan app:srcCompatsebagai ganti android:srcsaat memuat VectorDrawables. Jangan lupakan ini.

Sebab TextView, jika Anda menggunakan androidxversi Pustaka Dukungan, Anda dapat menggunakan app:drawableLeftCompat(atau kanan, atas, bawah) sebagai gantiapp:drawableLeft

Dalam kasus CheckBox/ RadioButton, gunakan app:buttonCompatsebagai pengganti android:button.

Jika Anda tidak menggunakan androidxversi Pustaka Dukungan dan Anda minSdkVersionadalah 17atau lebih tinggi atau menggunakan tombol, Anda dapat mencoba menyetel secara terprogram melalui

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

UPDATE - Jul / 2016

Mereka mengaktifkan kembali VectorDrawable di
Android Support Library 23.4.0

Untuk pengguna AppCompat , kami telah menambahkan API keikutsertaan untuk mengaktifkan kembali dukungan Vector Drawable dari sumber daya (perilaku yang ditemukan di 23.2) melalui AppCompatDelegate.setCompatVectorFromResourcesEnabled (true) - perlu diingat bahwa hal ini masih dapat menyebabkan masalah dengan penggunaan memori dan masalah saat memperbarui contoh Konfigurasi, oleh karena itu mengapa dinonaktifkan secara default.

Mungkin , build.gradlepengaturan sekarang sudah usang dan Anda hanya perlu mengaktifkannya dalam aktivitas yang tepat (namun perlu diuji).

Sekarang, untuk mengaktifkannya, Anda harus melakukan:

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

    ...
}

Jawaban Asli - Apr / 2016

Saya rasa ini terjadi karena Support Vector dinonaktifkan di versi library terbaru: 23.3.0

Menurut POST ini :

Untuk pengguna AppCompat, kami telah memutuskan untuk menghapus fungsionalitas yang memungkinkan Anda menggunakan vector drawable dari sumber daya pada perangkat pra-Lollipop karena masalah yang ditemukan dalam implementasi pada versi 23.2.0 / 23.2.1 (ISSUE 205236) . Menggunakan app: srcCompat dan setImageResource () terus berfungsi.

Jika Anda mengunjungi masalah ISSUE 205236 , tampaknya mereka akan mengaktifkannya di masa mendatang tetapi masalah memori tidak akan segera diperbaiki:

Pada rilis berikutnya saya telah menambahkan API keikutsertaan di mana Anda dapat mengaktifkan kembali dukungan VectorDrawable yang telah dihapus. Itu datang dengan peringatan yang sama seperti sebelumnya (penggunaan memori dan masalah dengan pembaruan Konfigurasi).

Saya memiliki masalah serupa. Jadi, dalam kasus saya, saya mengembalikan semua ikon yang menggunakan drawable vektor dari sumber daya ke gambar PNG lagi (karena masalah memori akan terus terjadi bahkan setelah mereka memberikan opsi untuk mengaktifkannya lagi).

Saya tidak yakin apakah ini adalah opsi terbaik, tetapi menurut saya ini memperbaiki semua kerusakan.

W0rmH0le
sumber
1
Terima kasih @Guilherme P. tetapi mengapa Anda tidak menghapus vectorDrawables.useSupportLibrary = truekebebasan untuk kembali mengaktifkan menghasilkan pngs pada waktu pembuatan lagi?
Behzad Bahmanyar
1
Itu dinonaktifkan di versi terbaru v23.3.0 karena masalah memori. Dengan cara ini, mereka tidak dapat menghasilkan png saat runtime ... Itulah mengapa dalam kesalahan logcat mereka mencetak: vektor tag tidak dikenal (atau semacamnya).
W0rmH0le
4
Berikut adalah petunjuk keikutsertaan plus.google.com/+AndroidDevelopers/posts/B7QhFkWZ6YX . Sayangnya VectorDrawables masih tidak berfungsi di perangkat Pre-Lollipop. Saya menggunakan Pustaka Dukungan 23.4.0 dan memiliki 'generatedDensities = []' dan 'vectorDrawables.useSupportLibrary = true' yang dipanggil di defaultConfig {}.
Adam Hurwitz
1
@AdamHurwitz Saya memperbarui jawabannya .. Sepertinya sudah diaktifkan lagi .. Namun, Anda harus mengaktifkannya secara berbeda sekarang.
W0rmH0le
1
@juwitaa. Anda harus menggunakan 'androidx.appcompat: appcompat: 1.1.0'
W0rmH0le
63

Saya memiliki masalah yang sama. Tapi melakukan banyak R&D, saya mendapat jawabannya.

Untuk penggunaan Imageview dan ImageButton, app:srcCompat="@drawable/...." dan untuk tampilan lain seperti Button, Textview, alih-alih menggunakan "drawableLeft/right..."XML, tetapkan drawable secara terprogram sebagai:

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

Dan gunakan "AppCompatResources" untuk mendapatkan drawable.

Shashank Kapsime
sumber
60

Untuk menguraikan jawaban lain yang sangat bagus , berikut adalah diagram yang dapat membantu Anda. Valid jika Anda memiliki Pustaka Dukungan dari 23.4.0 hingga setidaknya 25.1.0.

Cheatsheet VectorDrawable

David Ferrand
sumber
1
jika Anda mencoba menyetel drawableLeft, bungkus di dalam drawable seperti yang disebutkan di sini. medium.com/@chrisbanes/…
nizam.sp
Terima kasih bagan ini banyak membantu kami.
diam
39

Jawaban dari Guillherme P cukup mengagumkan. Hanya untuk membuat sedikit perbaikan, Anda tidak perlu menambahkan baris itu di setiap aktivitas, jika Anda menambahkannya sekali di kelas Aplikasi, itu akan berfungsi juga.

public class App extends Application {

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

INGAT: Anda masih harus mengaktifkan penggunaan pustaka dukungan di gradle:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Selain itu, pastikan Anda menggunakan versi support library yang lebih besar dari v23.4, ketika Google menambahkan kembali dukungan untuk Drawable Containers untuk VectorDrawables ( catatan rilis )

Memperbarui

Dan untuk perubahan kode:

  1. Pastikan untuk memperbarui ke app:srcCompat setiap tempat yang menerima android:srcatribut (IDE akan memperingatkan Anda jika tidak valid seperti untuk<bitmap> tag).
  2. Untuk drawableLeft, drawableStart, drawableRight, drawableEndatribut yang digunakan dalam TextViewdan pandangan yang sama, Anda harus mengatur mereka pemrograman untuk saat ini. Contoh pengaturan 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);
    }
    
Benny
sumber
ingat bahwa Anda harus MENGAKTIFKAN penggunaan pustaka dukungan untuk vector drawable di gradle: vectorDrawables.useSupportLibrary = true
Benny
2
Ya. Aku tahu. Namun diperlukan pembungkus agar vector drawable berfungsi sebagai drawable untuk TexView, jadi jawaban ini tidak lengkap.
cesards
1
Jawaban yang bagus. Ini sangat bagus untuk aplikasi dengan semua aktivitasnya yang diperluas dari aktivitas dasar kustom.
Hong
14

Saya memiliki masalah yang sama. Dan perbaiki dengan menghapus

vectorDrawables.useSupportLibrary = true

Versi target saya adalah 25 dan pustaka dukungan adalah

 compile 'com.android.support:appcompat-v7:25.3.1'
Rajesh Nasit
sumber
1
ini berhasil untuk saya. Terima kasih. Saya baru saja menghapusnyavectorDrawables.useSupportLibrary = true
Android Mediocre
Saya pikir ini bukan cara yang tepat untuk melakukannya, Bagaimanapun saya memberikan suara positif untuk jawaban Anda. !!
Harish Reddy
Terima kasih. t bekerja untuk aplikasi saya. Semua vector drawable masih berfungsi jika telah dihapus. Aplikasi menggunakan com.android.support:appcompat-v7:28.0.0
Hong
10

VectorDrawables pada pra-lollipop seharusnya berfungsi dengan baik tanpa menggunakan

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

Jika Anda ingin menggunakan VectorDrawables di dalam ImageViews, Anda bisa menggunakan atribut srcCompatdan itu akan berfungsi, tetapi di dalam Buttons atau TextView tidak , jadi Anda perlu menggabungkan Drawable ke dalam InsetDrawable atau LayerDrawable. Ada trik lain yang saya temukan, jika Anda menggunakan data binding, Anda dapat melakukan ini:

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

Itu akan bekerja secara ajaib, saya belum menyelidiki apa yang terjadi di balik layar, tapi saya rasa TextView menggunakan metode getDrawable dari AppCompatResources atau yang serupa.

cesards
sumber
Bagaimana cara mengatur gambar vektor di selector?
Tushar Gogna
setelah menyetel vectorDrawables.useSupportLibrary = true di gradle default dan AppCompatDelegate.setCompatVectorFromResourcesEnabled (true); dalam aktivitas saat membuat Untuk menghindari error pada android: drawableleft di Textview , setel drawble ke kiri ke textview secara terprogram untuk examlple: textview.setCompoundDrawablesWithIntrinsicBounds (R.drawable.movie, 0, 0, 0);
Afjalur Rahman Rana
7

Banyak R & d, akhirnya mendapatkan solusi ini untuk kerusakan pada perangkat pra-lollipop.

Untuk Imageview

  • gunakan app: srcCompat, bukan android: src

Untuk TextView / EditText

  • Hapus drawable , drawableright .... dan setel dari kode java drawable.

txtview.setCompoundDrawablesWithIntrinsicBounds (AppCompatResources.getDrawable (EventDetailSinglePage.this, R.drawable.ic_done_black_24_n), null, null, null);

Untuk Build.gradle

vectorDrawables.useSupportLibrary = true

Jatin Mandanka
sumber
1
Itu adalah solusi unik yang bekerja pada TextInputEditText.
heronsanches
1
Awsome, ini memecahkan masalah saya. Ini harus menjadi jawaban yang diterima.
DJtiwari
7

Penggunaan cara termudah:

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

dan ... gunakan saja app:**Compatuntuk kesesuaian. Juga tambahkan dukungan pada build.gradle(modul)

android {
   defaultConfig {
       vectorDrawables.useSupportLibrary = true
   }
}
Hamed Jaliliani
sumber
app: drawableEndCompat dan app: drawableRightCompat hampir sama jika bahasa
Inggrisnya
5

Bagi siapa saja yang mengupgrade ke android gradle 3.0 dan lebih tinggi, tidak perlu menggunakan AppCompatDelegate.setCompatVectorFromResourcesEnabled(true), atau mengatur vectorDrawables.useSupportLibrary = true(menambahkan ini akan menyebabkan masalah) dan gunakanapp:srcCompat , itu hanya berfungsi.

Luangkan waktu dua hari untuk mengetahuinya, dan belum menemukan dokumen terkait di dokumen google ...

Geng Jiawen
sumber
Menarik, saya menggunakan gradle 3.3.0 dan solusi ini berhasil. Namun, Android Studio masih meminta saya mengaktifkan set vectorDrawables.useSupportLibrary = true.
masterwok
2

Saya menggunakan VectorDrawables pada perangkat Pre-lollipop dan inilah cara saya melakukannya: -

Langkah 1: Letakkan ini di gradle level aplikasi Anda.

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Langkah 2:

Letakkan ini di kelas Aplikasi Anda dan jangan lupa untuk mendaftarkan kelas Aplikasi Anda di file manifes.

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

Langkah 3:

Dapatkan VectorDrawables menggunakan,

imageView.setImageDrawable(ContextCompat.getDrawable(this, R.drawable.my_vector_drawable));
Parag Kadam
sumber
2

Setelah menggunakan kode di bawah ini.

android {
  defaultConfig {
  vectorDrawables.useSupportLibrary = true  
                }
        }




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

Namun, masalah gambar vektor ada untuk atribut di bawah ini

DrawableEnd, DrawableStart, DrawableTop, DrawableBottom, Latar Belakang

Dalam kasus ini, ikuti seperti di bawah ini, Daripada mereferensikan gambar vektor secara langsung gunakan tag pemilih sebagai file drawable perantara.

Contoh:

ic_war 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_war 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 Anda.

<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"
       />
Rajesh Gr
sumber
Terima kasih !!! Untuk properti latar belakang, menambahkan selektor di antaranya daripada langsung menggunakan drawable vektor berfungsi untuk api pra-lollipop (19).
Ankur
dalam kasus saya, ini masih tidak berfungsi untuk API (16), bahkan dibungkus denganselector
mochadwi
1

Kami mencoba 3 hal

vectorDrawables.useSupportLibrary = true

Menyetel setCompatVectorFromResourcesEnabled di kelas Aplikasi

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

Dan gunakan app:srcCompat

Tetapi bahkan setelah itu gagal

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

kemudian kami menemukan bahwa SVG kami memiliki tag Gradient. Mengonversi tag gradien ke jalur individu untuk di bawah API <= 23 dan menggunakan SVG API> = 24 yang sama berhasil.

Dapatkan bantuan dari jawaban ini https://stackoverflow.com/a/47783962/2171513

Aalap
sumber
Saya tidak tahu mengapa tidak ada yang suka ini, tetapi ini sebenarnya bisa menjadi solusi untuk masalah saya. Terima kasih
DevMike01
1

Saya berjuang dengan ini selama berjam-jam.

Saya mencoba semua yang diminta jawaban ini, tetapi aplikasi saya tidak berhenti mogok. Saya menghapus baris ini: app:srcCompat="@drawable/keyboard"dan aplikasi saya berhenti mogok. dan kemudian ketika saya menambahkan kembali hal yang sama, itu mulai macet lagi. Jadi saya memutuskan untuk membuka file itu dan saya melihat kesalahan pada baris pertama yang mengatakan

"'Keyboard' drawable tidak memiliki deklarasi di folder drawable dasar; hal ini dapat menyebabkan error.

Saya mengklik kanan file tersebut dan mengklik "Show in explorer" dan itu tidak ada di folder drawable tetapi di direktori drawable-v24. Jadi saya menyalinnya dan menempelkannya ke direktori drawable dan akhirnya menyingkirkan error.

Fahad Maqsood Qazi
sumber
0

Cukup tumpang tindih vector drawable ke state-list maka masalah akan terpecahkan

Misalnya Anda memiliki gambar vektor panah belakang:

ic_back_arrow.xml

ya, Anda harus tumpang tindih dengan daftar lapisan 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>

Karena logika:

vectorDrawables.useSupportLibrary = true

dan

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

tidak akan membantu Anda di beberapa perangkat China dan perangkat samsung yang lebih lama. Jika Anda tidak tumpang tindih, itu akan gagal.

Tuan Boyfox
sumber
-2

Saran Guilherme P tidak berhasil untuk saya. Saya melanjutkan dan membuat keputusan untuk menggunakan png di mana saya perlu melakukan hal-hal di luar app: srcCompat yaitu drawableLeft, drawableRight, dll. Ini adalah perubahan yang cukup mudah dilakukan, dan tidak memiliki masalah memori potensial AppCompatDelegate.setCompatVectorFromResourcesEnabled ( benar); memperkenalkan.

Ryan Newsom
sumber
-3

Alternatif jawaban Benny adalah membuat Activitysuperclass:

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

  //...
}

Sekarang perpanjang, VectorDrawableActivitybukan AppCompatActivity.

Kode-Magang
sumber
@cesards Mengapa tidak?
Code-Apprentice