Lolipop öncesi kilitlenmede Android vektör Drawables'ı kullanma


95

Lollipop'tan önce android'de vektör çekmeceleri kullanıyorum ve bunlar kitaplıklarımdan ve araç sürümlerinden bazıları:

  • Android Studio: 2.0
  • Android Gradle Eklentisi: 2.0.0
  • Derleme Araçları: 23.0.2
  • Android Destek Kitaplığı: 23.3.0

Bu mülkü uygulama düzeyime ekledim Build.Gradle

android {  
  defaultConfig {  
    vectorDrawables.useSupportLibrary = true  
   }  
}

Ayrıca, Android resmi Blog'unda ( buraya bağlantı ) belirtildiği gibi LayerDrawable (layer_list) gibi ekstra bir drawable kullandığımı da belirtmekte fayda var .app:srcCompat

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

Uygulamanın dışında vektör çekmecelerine doğrudan referans olduğunu göreceksiniz: srcCompat, Lollipop'tan önce başarısız olacaktır. Bununla birlikte, AppCompat, StateListDrawable, InsetDrawable, LayerDrawable, LevelListDrawable ve RotateDrawable gibi başka bir çekilebilir kapta referans verildiğinde vektör çekilebilir öğelerin yüklenmesini destekler. Bu kullanarak indirection normalde destek vektör drawables mümkün olmaz drawableLeft özniteliği:, bu tür TextView'un en android olarak durumlarda vektör drawables kullanabilirsiniz.

Her app:srcCompatşeyi kullandığımda her şey yolunda gidiyor, ancak kullandığımda:

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

üzerine ImageView, ImageButton, TextViewveya EditTextLollipop öncesinde, bir expection atar:

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


VectorDrawable'ı drawableLeft, drawable Right, drawableTop, drawableBottom ile nasıl kullandığınızı görmek için Bu yanıtı
Behzad Bahmanyar

Cevabımı buradan kontrol edebilir misin? stackoverflow.com/a/40523623/2557258
Yazon2006

Benim durumumda, boş çekmeceler doğru pakette değildi (proje görünümünü aç) orjinal cevap burada stackoverflow.com/a/35836318/2163045
murt

Yanıtlar:


105

EN SON GÜNCELLEME - Haziran / 2019

Destek Kitaplığı, orijinal cevaptan bu yana biraz değişti. Artık Gradle için Android eklentisi bile derleme zamanında otomatik olarak PNG oluşturabilir. Dolayısıyla, bugünlerde işe yaraması gereken iki yeni yaklaşım aşağıdadır. Daha fazla bilgiyi burada bulabilirsiniz :

PNG Üretimi

Gradle, derleme sırasında varlıklarınızdan otomatik olarak PNG görüntüleri oluşturabilir. Ancak, bu yaklaşımda, tüm xml öğeleri desteklenmez . Bu çözüm kullanışlıdır çünkü kodunuzda veya build.gradle'da herhangi bir değişiklik yapmanız gerekmez. Sadece Android Eklentisi 1.5.0 veya üstünü ve Android Studio 2.2 veya üstünü kullandığınızdan emin olun .

Bu çözümü uygulamamda kullanıyorum ve iyi çalışıyor. Ek build.gradle bayrağı gerekmez. Kesmeye gerek yok. Eğer giderseniz / yapı / üretilen / res / pngs / ... tüm oluşturulan PNGs görebilirsiniz.

Dolayısıyla, basit bir simgeniz varsa (tüm xml öğeleri desteklenmediğinden), bu çözüm sizin için işe yarayabilir. Android Studio'nuzu ve Gradle için Android eklentinizi güncellemeniz yeterlidir.

Destek Kitaplığı

Muhtemelen, sizin için işe yarayacak çözüm budur. Buraya geldiyseniz, bu, Android Studio'nuzun PNG'leri otomatik olarak oluşturmadığı anlamına gelir. Yani, uygulamanız kilitleniyor.

Veya belki de Android Studio'nun hiç PNG oluşturmasını istemiyorsunuz.

XML öğesinin bir alt kümesini destekleyen "Otomatik PNG oluşturma" dan farklı olarak, bu çözüm tüm xml etiketlerini destekler. Yani, vektör çiziminize tam desteğiniz var.

Desteklemek için önce build.gradle dosyanızı güncellemelisiniz :

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
}

Ve sonra yükleme sırasında app:srcCompatyerine kullanın . Bunu unutma.android:srcVectorDrawables

İçin TextViewkullandığınız takdirde, androidxDestek Kütüphanesi'nin sürümünü kullanabilirsiniz app:drawableLeftCompat(veya sağ, üst, alt) yerineapp:drawableLeft

Durumunda CheckBox/ RadioButtonkullanmak app:buttonCompatyerine android:button.

Eğer kullanmıyorsanız androidxDestek Kütüphanesi ve sürümünü minSdkVersionIS 17veya daha yüksek veya bir düğmeyi kullanarak, sen aracılığıyla programlı ayarlamak deneyebilir

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

GÜNCELLEME - Temmuz / 2016

VectorDrawable'ı Android Destek Kitaplığı 23.4.0'da yeniden etkinleştirdiler

AppCompat kullanıcıları için , biz ekledik opt- için API desteği Vektör Drawables AppCompatDelegate.setCompatVectorFromResourcesEnabled (doğru) yolu ile kaynakların (davranış 23.2 bulundu) den yeniden etkinleştirmek - Unutmayın bu hala bellek kullanımı ve ilgili sorunlara neden olabilir Yapılandırma örneklerini güncelleme sorunları, bu nedenle varsayılan olarak devre dışı bırakılmasının nedeni.

Belki , build.gradleayar artık geçersizdir ve sadece uygun aktivitelerde etkinleştirmeniz gerekir (ancak, test etmeniz gerekir).

Şimdi, etkinleştirmek için yapmanız gerekenler:

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

    ...
}

Orijinal Cevap - Nisan / 2016

Bunun en son kütüphane sürümünde Destek Vektörü devre dışı bırakıldığı için olduğunu düşünüyorum: 23.3.0

Bu POST'a göre :

AppCompat kullanıcıları için, 23.2.0 / 23.2.1 (ISSUE 205236) sürümündeki uygulamada bulunan sorunlar nedeniyle, Lollipop öncesi cihazlarda kaynaklardan vektör çizimlerini kullanmanıza izin veren işlevselliği kaldırmaya karar verdik . App: srcCompat ve setImageResource () kullanımı çalışmaya devam eder.

Sayı 205236'yı ziyaret ederseniz , gelecekte etkinleştirilecek gibi görünüyor ancak bellek sorunu yakında çözülmeyecek :

Bir sonraki sürümde, kaldırılan VectorDrawable desteğini yeniden etkinleştirebileceğiniz bir tercihe bağlı API ekledim. Daha önce olduğu gibi aynı uyarılarla birlikte gelir (bellek kullanımı ve Yapılandırma güncellemesiyle ilgili sorunlar).

Benzer bir sorun yaşadım. Bu yüzden, benim durumumda, vektör çizimini kullanan tüm simgeleri kaynaktan tekrar PNG görüntülerine geri döndürdüm (çünkü bellek sorunu, tekrar etkinleştirmek için bir seçenek sağladıktan sonra bile olmaya devam edecek).

Bunun en iyi seçenek olup olmadığından emin değilim, ancak bence tüm çökmeleri düzeltir.


1
Teşekkürler @Guilwell P. vectorDrawables.useSupportLibrary = truepng oluşturma zamanında tekrar png oluşturmaya geri dönmek için neden peroperty'yi kaldırmadınız ?
Behzad Bahmanyar

1
Bu, bellek sorunları nedeniyle en son sürüm v23.3.0'da devre dışı bırakıldı. Bu şekilde, çalışma zamanında png üretemezler ... Bu yüzden logcat hatası yazdırırlar: bilinmeyen etiket vektörü (veya buna benzer bir şey).
W0rmH0le

4
Kaydolma talimatları plus.google.com/+AndroidDevelopers/posts/B7QhFkWZ6YX burada . Maalesef VectorDrawables hala Pre-Lollipop cihazında çalışmıyor. 23.4.0 Destek Kitaplığı'ndayım ve defaultConfig {} 'de çağrılan hem' generatedDensities = [] 'hem de' vectorDrawables.useSupportLibrary = true 'var.
Adam Hurwitz

1
@AdamHurwitz Cevabı güncelledim .. Görünüşe göre tekrar etkinleştirildi .. Ancak şimdi farklı bir şekilde etkinleştirmelisiniz.
W0rmH0le

1
@juztcode Haklısın. 'Androidx.appcompat: appcompat: 1.1.0'
W0rmH0le

63

Ben de aynı sorunu yaşadım. Ancak çok fazla Ar-Ge yaparak cevabı aldım.

Imageview ve ImageButton kullanımı app:srcCompat="@drawable/...." için ve Button, Textview gibi diğer görünümler "drawableLeft/right..."için XML'de kullanmak yerine çekilebilir öğeleri programlı olarak şu şekilde belirtin:

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

Ve çekilebilir olanı elde etmek için "AppCompatResources" kullanın.



39

Guillwell P'nin cevabı oldukça harika. Sadece küçük bir iyileştirme yapmak için, her aktiviteye bu satırı eklemenize gerek yoktur, eğer onu Uygulama sınıfına bir kez eklerseniz, aynı zamanda çalışacaktır.

public class App extends Application {

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

UNUTMAYIN: Gradle'da destek kitaplığının kullanımını etkinleştirmiş olmanız gerekir:

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Ayrıca, Google VectorDrawables için Çekilebilir Konteynerler desteğini geri eklediğinde ( sürüm notu ) v23.4'ten daha büyük bir destek kitaplığı sürümü kullandığınızdan emin olun.

Güncelleme

Ve kod değişiklikleri için:

  1. Özelliği app:srcCompatkabul eden her yere güncelleme yaptığınızdan emin olun android:src(IDE, <bitmap>etiket için olduğu gibi geçersizse sizi uyaracaktır ).
  2. İçin drawableLeft, drawableStart, drawableRight, drawableEndkullanılan öznitelikleri TextViewve benzeri görünümler, şimdilik programlı bunları gerekecektir. Bir ayar örneği 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
Benny

2
Evet. Biliyorum. Ancak vektör çekilebilir öğelerinin TexViews için çekilebilir öğeler olarak çalışmasını sağlamak için bir sarmalayıcı gereklidir, bu nedenle bu yanıt eksiktir.
2016

1
Mükemmel cevap. Tüm etkinliklerinin özel bir temel etkinlikle genişletildiği uygulamalar için özellikle iyidir.
Hong

14

Ben de aynı sorunu yaşadım. Ve kaldırarak düzeltin

vectorDrawables.useSupportLibrary = true

Hedef sürümüm 25 ve destek kitaplığı

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

1
bu benim için çalıştı. Teşekkürler. Bunu yeni kaldırdımvectorDrawables.useSupportLibrary = true
Android Vasat

Sanırım bunu yapmanın doğru yolu bu değil, Her iki durumda da cevabına oy verdim. !!
Harish Reddy

Teşekkür ederim. t benim uygulamam için çalışıyor. Tüm vektör çekilebilir öğeleri, kaldırılmışsa yine de çalışır. Uygulama com.android.support:appcompat-v7:28.0.0
Hong

10

Pre-lolipop'taki VectorDrawables, kullanılmadan düzgün çalışmalıdır

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

VectorDrawables'ı ImageViews içinde kullanmak istiyorsanız, özniteliği kullanabilirsiniz srcCompatve çalışacaktır, ancak Buttons veya TextViews içinde bu olmaz , bu nedenle Drawable'ı bir InsetDrawable veya LayerDrawable'a sarmalamanız gerekir. Bulduğum başka bir numara daha var, eğer veri bağlamayı kullanıyorsanız, bunu yapabilirsiniz:

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

Bu sihirli bir şekilde işe yarayacak, perde arkasında neler olduğunu araştırmadım, ancak TextView'in AppCompatResources veya benzerinden getDrawable yöntemini kullandığını tahmin ediyorum.


Vektör görüntüsü seçici olarak nasıl ayarlanır?
Tushar Gogna

vectorDrawables.useSupportLibrary = gradle varsayılan ve AppCompatDelegate.setCompatVectorFromResourcesEnabled (true) içinde true ayarlandıktan sonra ; oluşturmada etkinlikte android ile çökmeyi önlemek için : Textview'da drawableleft , examlple için programlı olarak metin görünümüne sol çekmeyi ayarlayın: textview.setCompoundDrawablesWithIntrinsicBounds (R.drawable.movie, 0, 0, 0);
Afjalur Rahman Rana

7

Çok fazla Ar-Ge, sonunda lolipop öncesi cihazlardaki çökmeler için bu çözümü alıyorum.

Imageview için

  • Kullanım uygulaması: srcCompat yerine android ait: src

TextView / EditText için

  • Drawableleft'i kaldırın , drawableright .... ve çekilebilir java kodundan ayarlayın.

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

Build.gradle için

vectorDrawables.useSupportLibrary = true


1
TextInputEditText üzerinde çalışan benzersiz çözümdü.
heronsanches

1
Harika, bu benim sorunum çözüldü. Bu cevap kabul edilmelidir.
DJtiwari

7

En kolay yol kullanımı:

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

ve ... sadece app:**Compatuyumluluk için kullanın . Ayrıca build.gradle(modül) üzerine destek ekleyin

android {
   defaultConfig {
       vectorDrawables.useSupportLibrary = true
   }
}

app: drawableEndCompat ve app: drawableRightCompat, İngilizce ise hemen hemen aynı şeydir
Hossam Hassan

5

Android gradle 3.0 ve üzeri sürümlere yükseltme yapan herkes için, kullanmaya AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)veya ayarlamaya vectorDrawables.useSupportLibrary = true(bu soruna neden olur) ve kullanmaya gerek yoktur app:srcCompat, sadece çalışır.

Bunu anlamak için bana iki gün ayırın ve google'ın dokümanlarında ilgili herhangi bir doküman bulamadım ...


İlginç, 3.3.0 gradle kullanıyorum ve bu çözüm çalışıyor. Ancak, Android Studio hala vectorDrawables.useSupportLibrary = true setini etkinleştirmemi söylüyor.
masterwok

3

Aşağıdaki kodu kullandıktan sonra.

android {
  defaultConfig {
  vectorDrawables.useSupportLibrary = true  
                }
        }




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

yine de, aşağıdaki öznitelikler için vektör görüntüleri sorunu mevcuttur:

DrawableEnd, DrawableStart, DrawableTop, DrawableBottom, Arkaplan

Bu durumda, lütfen aşağıdaki gibi takip edin, Vektör görüntüsüne atıfta bulunmak yerine doğrudan ara çekilebilir dosya olarak seçici etiketi kullanın.

Misal:

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'unuz.

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

Teşekkürler !!! Arka plan özelliği için, lolipop öncesi api (19) için doğrudan vektör çekilebilir kullanmak yerine arasına seçici eklemek çalıştı.
Ankur

benim durumumda, bu hala API (16) için çalışmıyor, hattaselector
mochadwi

2

VectorDrawables'ı Lolipop öncesi cihazlarda kullanıyorum ve şu şekilde yapıyorum: -

1. Adım: Bunu, uygulama düzeyi notunuza ekleyin.

android {
  defaultConfig {
    vectorDrawables.useSupportLibrary = true
  }
}

Adım 2:

Bunu Application sınıfınıza koyun ve Application sınıfınızı manifest dosyasına kaydetmeyi unutmayın.

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

Aşama 3:

VectorDrawables'ı kullanarak alın,

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

1

3 şey denedik

vectorDrawables.useSupportLibrary = true

Uygulama sınıfında setCompatVectorFromResourcesEnabled'ı ayarlama

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}

Ve kullan app:srcCompat

Ama ondan sonra bile başarısız oluyordu

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

sonra SVG'mizin bir Gradyan etiketi olduğunu anladık. Gradyan etiketini aşağıdaki API <= 23 ve aynı SVG API> = 24 için ayrı yollara dönüştürmek işe yaradı.

Bu yanıttan yardım aldım https://stackoverflow.com/a/47783962/2171513


Neden kimse buna olumlu oy vermiyor bilmiyorum, ama bu aslında sorunumun çözümü olabilir. Teşekkürler
DevMike01

1

Bununla saatlerce uğraşıyordum.

Bu yanıtların bana söylediği her şeyi denedim, ancak uygulamam çökmeyi bırakmadı. Bu satırı sildim: app:srcCompat="@drawable/keyboard"ve uygulamamın çökmesi durdu. ve sonra aynı şeyi tekrar eklediğimde, tekrar çökmeye başladı. Bu yüzden o dosyayı açmaya karar verdim ve ilk satırda bir hata gördüm

"Çekilebilir 'Klavye'nin temel çekilebilir klasöründe hiçbir beyanı yoktur; bu, çökmelere neden olabilir.

Dosyaya sağ tıkladım ve "Gezginde göster" e tıkladım ve çekilebilir klasörde değil, çekilebilir-v24 dizinindeydi. Ben de kopyalayıp çekilebilir dizine yapıştırdım ve sonunda çökmelerden kurtuldum.


0

Basitçe durum listesine çekilebilir vektör üst üste bindirin, sonra sorun çözülecektir

Örneğin, geri ok vektör resminiz var:

ic_back_arrow.xml

evet, xml katman listesi (ic_back_arrow_vector_vector.xml) ile örtüştürmelisiniz:

<?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>

Çünkü mantık:

vectorDrawables.useSupportLibrary = true

ve

AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);

bazı Çin cihazlarında ve daha eski Samsung cihazlarında size yardımcı olmayacaktır. Eğer üst üste binmezseniz başarısız olur.


-2

Guilherme P'nin önerisi benim için işe yaramıyordu. Devam ettim ve uygulama dışında şeyler yapmam gereken yerlerde png'leri kullanmaya karar verdim: srcCompat, yani drawableLeft, drawableRight, vb. Bu, yapılması oldukça kolay bir değişiklikti ve olası bellek sorunları yok AppCompatDelegate.setCompatVectorFromResourcesEnabled ( doğru); tanıtır.


-3

Benny'nin cevabına bir alternatif, bir Activityüst sınıf oluşturmaktır :

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

  //...
}

Şimdi VectorDrawableActivityyerine uzatın AppCompatActivity.


@cesards Neden olmasın?
Code-Apprentice
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.