Android: DrawableRight kullanarak Buttons ve TextViews'ta VectorDrawable kullanmak mümkün mü?


120

VectorDrawable varlıklarını bir metin görünümünde veya görüntü görünümünde kullandığımda, "android: DrawableRight" / "android: DrawableEnd" / "android: DrawableStart" / "android: DrawableLeft" kullanırken çalışma zamanı çökmesi alıyorum.

Uygulama herhangi bir uyarı olmaksızın iyi bir şekilde derleyecektir.

Ben kullanıyorum

  • Gradle 1.5
  • Destek Kitaplığı 23.2 ('com.android.support:appcompat-v7:23.2.0')

Yine de bulduğum şey, SVG'leri Java'da bu gibi çökmeler olmadan programlı olarak atayabileceğim.

TextView tv = (TextView) findViewById(R.id.textView);
tv.setCompoundDrawablesWithIntrinsicBounds(null,null, getResources().getDrawable(R.drawable.ic_accessible_white_36px),null);

(Bunun 23.2 için bir destek kitaplığı hatası olduğundan şüpheleniyorum.)

Ancak SVG varlıkları için drawableRight vb. Kullanmak mümkün müdür?

İşte düzenim

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="au.com.angryitguy.testsvg.MainActivity">


<TextView
    android:id="@+id/textView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:drawableRight="@drawable/ic_accessible_white_36px"
    android:background="@color/colorPrimary"
    android:textColor="#FFFFFF"
    android:textSize="22sp"
    android:text="Hello World!"/>
</RelativeLayout>

İşte benim faaliyetim

package au.com.angryitguy.testsvg;

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        }
    }

İşte Google'ın materyal tasarım sitesinden değiştirilmemiş VectorDrawable varlığı.

<vector android:height="24dp" android:viewportHeight="24.0"
    android:viewportWidth="24.0" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
    <path android:fillColor="#FFFFFF" android:pathData="M12,4m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
    <path android:fillColor="#FFFFFF" android:pathData="M19,13v-2c-1.54,0.02 -3.09,-0.75 -4.07,-1.83l-1.29,-1.43c-0.17,-0.19 -0.38,-0.34 -0.61,-0.45 -0.01,0 -0.01,-0.01 -0.02,-0.01L13,7.28c-0.35,-0.2 -0.75,-0.3 -1.19,-0.26C10.76,7.11 10,8.04 10,9.09L10,15c0,1.1 0.9,2 2,2h5v5h2v-5.5c0,-1.1 -0.9,-2 -2,-2h-3v-3.45c1.29,1.07 3.25,1.94 5,1.95zM12.83,18c-0.41,1.16 -1.52,2 -2.83,2 -1.66,0 -3,-1.34 -3,-3 0,-1.31 0.84,-2.41 2,-2.83L9,12.1c-2.28,0.46 -4,2.48 -4,4.9 0,2.76 2.24,5 5,5 2.42,0 4.44,-1.72 4.9,-4h-2.07z"/>
</vector>

İşte benim uygulama build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    defaultConfig {
        applicationId "au.com.angryitguy.testsvg"
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
        // Stops the Gradle plugin’s automatic rasterization of vectors
        generatedDensities = []
    }
    // Flag to tell aapt to keep the attribute ids around
    aaptOptions {
        additionalParameters "--no-version-vectors"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.2.0'
}

İşte kaza. (Metin görünümüne atıfta bulunan şişirme hatalarına dikkat edin.)

java.lang.RuntimeException: Unable to start activity ComponentInfo{
    au.com.angryitguy.testsvg/au.com.angryitguy.testsvg.MainActivity}: 
    android.view.InflateException: Binary XML file line #13: 
    Error inflating class TextView

at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
at android.app.ActivityThread.access$600(ActivityThread.java:130)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:137)
at android.app.ActivityThread.main(ActivityThread.java:4745)
...

Caused by: android.view.InflateException: 
    Binary XML file line #13: Error inflating class TextView
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267)
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129)
at au.com.angryitguy.testsvg.MainActivity.onCreate(MainActivity.java:14)
at android.app.Activity.performCreate(Activity.java:5008)
...

Caused by: android.content.res.Resources$NotFoundException: 
    File res/drawable/ic_accessible_white_36px.xml from drawable resource ID #0x7f02004b
at android.content.res.Resources.loadDrawable(Resources.java:1918)
at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
at android.widget.TextView.<init>(TextView.java:622)
at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:60)
at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:56)
at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103)
at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:963)
at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1022)
at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44)
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:675)
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267) 
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129) 
at au.com.angryitguy.testsvg.MainActivity.onCreate(MainActivity.java:14) 
at android.app.Activity.performCreate(Activity.java:5008) 
...

Caused by: org.xmlpull.v1.XmlPullParserException:
    Binary XML file line #1: invalid drawable tag vector
at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:877)
at android.graphics.drawable.Drawable.createFromXml(Drawable.java:818)
at android.content.res.Resources.loadDrawable(Resources.java:1915)
at android.content.res.TypedArray.getDrawable(TypedArray.java:601) 
at android.widget.TextView.<init>(TextView.java:622) 
at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:60) 
at android.support.v7.widget.AppCompatTextView.<init>(AppCompatTextView.java:56) 
at android.support.v7.app.AppCompatViewInflater.createView(AppCompatViewInflater.java:103) 
at android.support.v7.app.AppCompatDelegateImplV7.createView(AppCompatDelegateImplV7.java:963) 
at android.support.v7.app.AppCompatDelegateImplV7.onCreateView(AppCompatDelegateImplV7.java:1022) 
at android.support.v4.view.LayoutInflaterCompatHC$FactoryWrapperHC.onCreateView(LayoutInflaterCompatHC.java:44) 
at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:675) 
at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 
at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 
at android.support.v7.app.AppCompatDelegateImplV7.setContentView(AppCompatDelegateImplV7.java:267) 
at android.support.v7.app.AppCompatActivity.setContentView(AppCompatActivity.java:129) 
at au.com.angryitguy.testsvg.MainActivity.onCreate(MainActivity.java:14) 
at android.app.Activity.performCreate(Activity.java:5008) 
...

Hayır, yapamazsınız çünkü SVG dosyaları yerel olarak desteklenmez . Bunun yerine bir VectorDrawable kullanmanız gerekir (yalnızca SVG özelliklerinin bir alt kümesini kullanır).
Phantômaxx

2
VectorDrawable'ın drawableLeft, drawableRight, drawableTop, drawableBottom ile nasıl kullanıldığını görmek için Bu yanıtı
Behzad Bahmanyar

Bu işleri benim için buldum: android.jlelse.eu/…
Huy Tower

Yanıtlar:


186

SVG varlıkları için drawableRight vb. kullanılabilir mi?

Evet

AppCompatTextView hemen destekler app:drawableLeftCompat, app:drawableTopCompat, app:drawableRightCompat, app:drawableBottomCompat, app:drawableStartCompatve app:drawableEndCompatbileşik drawables gibi çekilebilir türleri backported destekleyen VectorDrawableCompat.

Bunu gradle dosyanıza ekleyin

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

Metin görünümünüzde kullanabilirsiniz

app:drawableLeftCompat
app:drawableStartCompat

App: drawableLeftCompat, app: drawableStartCompat in tuşlarını kullanırken sorun yaşarsanız, kitaplığınızı şu şekilde güncellemeniz gerekir:

androidx.appcompat: AppCompat: 1.2.0-alpha01

bir böcekleri vardı

androidx.appcompat: AppCompat: 1.1.0-alpha01

belgeleri görebilirsin


Veya henüz güncelleme yapmak istemiyorsanız, o zaman:

Google'ın yakın zamanda bu sorunla ilgili hiçbir şey yapmayacağı görüldüğünden, tüm uygulamalarım için daha sağlam ve yeniden kullanılabilir bir çözüm bulmam gerekiyordu:

  1. Önce uygulamanızın "res / values ​​/ attrs.xml" attrs.xml dosyasına özel TextView özniteliklerini ekleyin :

    <resources>
        <declare-styleable name="CustomTextView">
            <attr name="drawableStartCompat" format="reference"/>
            <attr name="drawableEndCompat" format="reference"/>
            <attr name="drawableTopCompat" format="reference"/>
            <attr name="drawableBottomCompat" format="reference"/>
        </declare-styleable>
    </resources>
  2. Ardından şunun gibi özel TextView sınıfı oluşturun:

    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.drawable.Drawable;
    import android.os.Build;
    import android.support.v7.content.res.AppCompatResources;
    import android.support.v7.widget.AppCompatTextView;
    import android.util.AttributeSet;
    
    public class CustomTextView extends AppCompatTextView {
        public CustomTextView(Context context) {
            super(context);
        }    
        public CustomTextView(Context context, AttributeSet attrs) {
            super(context, attrs);
            initAttrs(context, attrs);
        }
        public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initAttrs(context, attrs);
        }
    
        void initAttrs(Context context, AttributeSet attrs) {
            if (attrs != null) {
                TypedArray attributeArray = context.obtainStyledAttributes(
                        attrs,
                        R.styleable.CustomTextView);
    
                Drawable drawableStart = null;
                Drawable drawableEnd = null;
                Drawable drawableBottom = null;
                Drawable drawableTop = null;
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    drawableStart = attributeArray.getDrawable(R.styleable.CustomTextView_drawableStartCompat);
                    drawableEnd = attributeArray.getDrawable(R.styleable.CustomTextView_drawableEndCompat);
                    drawableBottom = attributeArray.getDrawable(R.styleable.CustomTextView_drawableBottomCompat);
                    drawableTop = attributeArray.getDrawable(R.styleable.CustomTextView_drawableTopCompat);
                } else {
                    final int drawableStartId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableStartCompat, -1);
                    final int drawableEndId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableEndCompat, -1);
                    final int drawableBottomId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableBottomCompat, -1);
                    final int drawableTopId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableTopCompat, -1);
    
                    if (drawableStartId != -1)
                        drawableStart = AppCompatResources.getDrawable(context, drawableStartId);
                    if (drawableEndId != -1)
                        drawableEnd = AppCompatResources.getDrawable(context, drawableEndId);
                    if (drawableBottomId != -1)
                        drawableBottom = AppCompatResources.getDrawable(context, drawableBottomId);
                    if (drawableTopId != -1)
                        drawableTop = AppCompatResources.getDrawable(context, drawableTopId);
                }
    
                // to support rtl
                setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, drawableTop, drawableEnd, drawableBottom);
                attributeArray.recycle();
            }
        }
    }
  3. Artık, özel niteliklerinizle herhangi bir düzende kolayca kullanabilirsiniz:

    <YOUR_VIEW_PACKAGE.CustomTextView
        android:id="@+id/edt_my_edit_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:drawableStartCompat="@drawable/your_vector_drawable" <!-- vector drawable -->
        app:drawableEndCompat="@drawable/your_vector_drawable" <!-- vector drawable -->
        app:drawableTopCompat="@drawable/your_vector_drawable" <!-- vector drawable -->
        app:drawableBottomCompat="@drawable/your_vector_drawable" <!-- vector drawable -->
        />
    • TextView'dan türetildikleri için Button , EditText ve RadioButton ile benzer şeyler yapabilirsiniz.

Bu yardımcı olur umarım :)


4
Çok faydalı cevap. Her neyse, Dadou'nun tam cevabını da okumanızı tavsiye ederim . Çıkarma vectorDrawables { useSupportLibrary = true }ne biz gelen build.gradlecevabın benim için çalıştı anlaşılacağı gibi.
Sam

Bunu yaptım ve şimdi şu sorunla karşılaşıyorum:
onclick'i XML'e eklediğimde

3
vectorDrawables useSupportLibrary = trueÇizginin kademeden kaldırılmasına katılmıyorum . Bunu kaldırdığınızda, görünümlerinizin içine yine de vektörler koyabilirsiniz, ancak bunlar pngs ile aynı şekilde yeniden boyutlandırılır, yani uzatılır ve grenli hale gelir. 5.0 / API21'in altındaki cihazların vektörleri doğru şekilde yeniden boyutlandırmasını ve böylece net görünmelerini istiyorsanız, bu satırı gradle dosyasında kullanmalısınız. Bu satırı satıra koymak, vektörleri yanlış kullandığınız alanları bulmak için IDE'yi çağırır ve sonra app:srcCompatXML aracılığıyla kullanmanız veya kod aracılığıylaVectorDrawableCompat.create()
Heinous Games

app:drawableEndCompatDaha iyi RTL desteği için nasıl eklenir ? Neden setCompoundDrawablesRelativeWithIntrinsicBoundsen az API seviye 17'ye ihtiyaç duyar.
Dr.jacky

1
Çekilebilirliği programlı olarak ayarlamaya ne dersiniz?
android geliştiricisi

77

Bu çözüm artık doğru değil. 23.3.0 sürümünden itibaren vektör çekmeceleri yalnızca uygulama aracılığıyla yüklenebilir: srcCompat veya setImageResource ()

Çekilebilir vektörünüzü katman listesine veya seçiciye kaydırmayı deneyin:

<TextView
    android:id="@+id/textView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:drawableRight="@drawable/ic_accessible_white_wrapped"
    android:background="@color/colorPrimary"
    android:textColor="#FFFFFF"
    android:textSize="22sp"
    android:text="Hello World!"/>

ic_accessible_white_wrapped.xml:

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

Bu iyi çalışıyor. Teşekkürler .. Ama görünen o ki "android: drawableXXXXX" de bir SVG'ye doğrudan atıfta bulunamazsınız, onu başka bir şeye sarmanız gerekir.
angryITguy

1
Evet. Doğrudan kullanamazsınız. Yalnızca uygulama olarak: srcCompat veya paketlenmiş veya programlı olarak. Bu, burada açıklanmıştır: android-developers.blogspot.ru/2016/02/…
Alexandr Shutko

Ahh .. teşekkürler .. Bahsettiğiniz paragrafı görebiliyorum. Öyleyse, size yapmamanızı söylerlerse bu hala bir hata mı? ;)
angryITguy

1
Bence her şey geriye dönük uyumlulukla ilgili. Görünüşe göre tam svg desteği almakta bir sorun var, bu yüzden bazı geçici çözümler yaptılar ...
Alexandr Shutko

2
23.3.0 destek sürümünden @HarishGyanani, artık destek değil. Etkinliğinize daha fazla komut eklemelisiniz: statik {if (Build.VERSION.SDK_INT <Build.VERSION_CODES.LOLLIPOP) {AppCompatDelegate.setCompatVectorFromResourcesEnabled (true); }}
Cuong Nguyen

75

Bulduğum en iyi yol:

Drawable leftDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_search);
search.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);

9
8/25/17 itibariyle benim için işe yarayan tek şey budur (çekilebilirliği programlı olarak ayarlamak). Aslında kullandım:Drawable drawable = VectorDrawableCompat.create(getResources(), status.getIconResId(), wrapper.getTheme()); statusButton.setCompoundDrawablesRelativeWithIntrinsicBounds(null, drawable, null, null);
saiyancoder

2
için minSdk setCompoundDrawablesWithIntrinsicBoundsolan 17 . Aksi takdirde bu harika çalışıyor.
Victor Rendina

1
MinSdk değeri 1 değil 17, muhtemelen benzer apise bakıyorsunuz. setCompoundDrawablesWithIntrinsicBounds => minSdk 1; setCompoundDrawablesRelativeWithIntrinsicBounds => minSdk 17
正宗 白 布鞋

Programlı ayar için en iyi çözüm, +1
Woton Sampaio

Bunu BindingAdapters ile kullandım ve verimli çalışıyor, teşekkürler!
Ric17101

61

Buradaki cevaplardan bazılarını tamamlamak için: VectorDrawable'ı drawableLeft(vb.) Olarak çalıştırabilirsiniz, ancak Destek Kitaplığı sürümüne bağlıdır ve bir bedeli vardır.

Hangi durumlarda işe yarar? Yaptığım bu diyagramı (- en azından - 25.1.0 Destek Kitaplığı 23.4.0 için geçerlidir) yardımına.

VectorDrawable hile sayfası


2
Harika, ancak statik bloktaki yöntem adını şu şekilde düzeltmelisinizsetCompatVectorFromResourcesEnabled
Vikas Patidar

1
setCompatVectorFromResourcesEnabled çözümü maalesef 25.3.1'de çalışmıyor
Ilja S.

From 23.3.0 version vector drawables can only be loaded via app:srcCompat or setImageResource()bu nedenle bu çözüm kullanımdan kaldırıldı ve çalışmayacak
user25

etkinleştirilmesi setCompatVectorFromSourcesEnabled(true), vektör çizimlerini android:backgroundAndroid 4.x'e yüklemeyi mümkün kılar. O yüzden teşekkürler! (Asıl vektörü tek bir öğe katmanı listesine
sarmanız gerekir

14

Diğer cevapların hiçbiri burada bir ekledik nasıl çalıştı VectorDrawablebir etmek TextView, kullanmak gerekir VectorDrawableCompat.create()ile uğraşırken VectorDrawablesaşağıda Android L:

TextView titleTextView = (TextView) viewHolder.getView(android.R.id.text1);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
{
       Drawable leftDrawable = AppCompatResources
                            .getDrawable(context, R.drawable.ic_tickbox);
       titleTextView.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
}
else
{
      //Safely create our VectorDrawable on pre-L android versions. 
       Drawable leftDrawable = VectorDrawableCompat
                            .create(context.getResources(), R.drawable.ic_tickbox, null);
       titleTextView.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
}

Kısa, tatlı ve anlamlı!


Bu, Android P ve minimum API seviyesi 26 (hedef 28) için çalıştı
MiStr

@MiStr - Aynı zamanda geriye dönük uyumlu :)
Sakiboy

9

Google'dan: Android Destek Kitaplığı 23.3.0'dan itibaren, destek vektör çekmeceleri yalnızca app: srcCompat veya setImageResource () .. aracılığıyla yüklenebilir.

http://android-developers.blogspot.ru/2016/02/android-support-library-232.html


1
bu şimdilik çözüm yok anlamına geliyor
Killer

Çizilebilir vektörünüzü katman listesine veya seçiciye kaydırmayı deneyin: <TextView android: id = "@ + id / textView" android: layout_width = "match_parent" android: layout_height = "wrap_content" android: drawableRight = "@ drawable / ic_accessible_white_wrapped" android: background = "@ color / colorPrimary" android: textColor = "# FFFFFF" android: textSize = "22sp" android: text = "Merhaba Dünya!" /> ic_accessible_white_wrapped.xml: <layer-list xmlns: android = " şemalar .android.com / apk / res / android "> <item android: drawable =" @ drawable / ic_accessible_white_36px "/> </layer-list>
Boş İşaretçi İstisnası

9

Vektör çizimlerini xml'de doğrudan ayarlamak mümkündür, ancak veri bağlama çerçevesini dahil ettiniz.

Sadece yaz

<TextView
...
android:drawableRight="@{@drawable/ic_accessible_white_36px}"/>

ve tüm düzeninizi bir <layout>etikete sarın , böylece temelde xml'niz şöyle görünür:

<?xml version="1.0" encoding="utf-8"?>
<layout>

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin"
        tools:context="au.com.angryitguy.testsvg.MainActivity">


        <TextView
            android:id="@+id/textView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimary"
            android:drawableRight="@{@drawable/ic_accessible_white_36px}"
            android:text="Hello World!"
            android:textColor="#FFFFFF"
            android:textSize="22sp"/>
    </RelativeLayout>
</layout>

Veri bağlama çerçevesini etkinleştirmek için şunu ekleyin:

android {
    ....
    defaultConfig {
        dataBinding {
            enabled = true
        }
    }
}

Bağlama kitaplığının diğer özelliklerini kullanmak zorunda değilsiniz

DÜZENLE:

Elbette, Lollipop öncesi vektör çekmecelerini kullanmak istiyorsanız,

vectorDrawables.useSupportLibrary = true

Yani build.gradle2 yeni komuta ihtiyacınız var:

android {
    ....
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
        dataBinding {
            enabled = true
        }
    }
}

sayesinde rkmax sözler için


Bu iyi bir fikir, ancak bunun çalışması için bir ciltleme adaptörü yazmanız gerekiyor. İşte çalışan bir örnek: gist.github.com/lisawray/78c33f76809d2bcbbec9983e2c141a70
BladeCoder

1
Bunun benim için çalıştığını söylemeliyim, ancak vectorDrawables.useSupportLibraryapp / build.gradle üzerinde etkinleştirmeniz ve ayrıca AppCompatDelegate.setCompatVectorFromResourcesEnabled (true) etkinliğini
eklemeniz gerekir

Bu build.gradle, çalışmamasının nedeni olarak defaultConfig eklemeyi unuttum
Hans M

Teşekkürler - sen bir hayat kurtarıcısın!
Van

Bu küçümsenmemiş bir cevap!
DYS

6

Tüm yanıtları gözden geçirdim ve en son Android studio 3.0.1 ve AppCompat Destek Kitaplığı 26.1.0'ı kullanarak bunun iyi çalıştığından emin olabilirim.

In build.gradle (uygulama) dosyası

android {
    compileSdkVersion 26
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }
}

dependencies {
    implementation 'com.android.support:appcompat-v7:26.1.0'
}

Ve Aktivite genişletme AppcompatActivity, bu dış yöntemleri, yani bir staticbloğu içerir.

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}  

veya bunun tüm uygulamaya uygulanmasını istiyorsanız, yalnızca bu satırı sınıf genişletme Applicationsınıfına ekleyin

override fun onCreate() {
    super.onCreate()
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true)
}

Xml'de metin görünümü

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center"
    android:orientation="vertical">

<TextView
        android:id="@+id/passName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawableLeft="@drawable/account_drawableleft_selector"
        android:drawablePadding="5dp"
        android:ellipsize="marquee"
        android:fontFamily="@font/montserrat_light_family"
        android:gravity="center_vertical"
        android:marqueeRepeatLimit="marquee_forever"
        android:paddingRight="10dp"
        android:scrollHorizontally="true"
        android:singleLine="true"
        android:textColor="@color/app_text_color"
        android:textSize="12sp"
        tools:text="Account Name" />
</LinearLayout>

account_drawableleft_selector.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_account_circle_24dp" /> <!-- checked -->
</selector>

Hangi API'de iyi çalışıyor? 19'u mu yoksa 20'yi mi denedin?
Divers

Kullanmak nasıl gösterebilir drawableRightiçin TextViewXML?
Divers

2
Yukarıda bahsedildiği gibi, vektör xml'yi doğrudan drawableLeft olarak kullanırsanız, bu çökme veya istisnayı hala alırsanız, geçici çözüm bu xml vektörünü Textview için drawableLeft için bir seçici olarak kullanmaktır. Düzenlenmiş cevapta görebileceğiniz kullanım.
Amit Tumkur

1
işe yaramayacak, TextView için doğrudan
xml'de

API 19 ve 20'de test edin. Bunun yerine uygulama sınıfında AppCompatDelegate.setCompatVectorFromResourcesEnabled'ı kullandım. Bir cazibe gibi çalışıyor!
Red M


5

Bu soruna geç kaldığım için bu soruyu cevaplamak için çok geç kaldım. TextView ile svg / vektör çekmecelerinde aynı sorunu yaşadım. Kendi özel çekmecenizi yapmak yerine, problemimi aşağıdaki gibi 2 satır kodla çözebilirim:

Drawable drawableTop = AppCompatResources.getDrawable(view.getContext(), iconId);
view.setCompoundDrawablesWithIntrinsicBounds(null, drawableTop, null, null);

Umarım size yardımcı olur.


Ön Lcihazlarla uyumlu değildir .
Sakiboy

@Sakiboy Evet, çünkü bu kodu minimum api 17 ile kullanıyorum.
Rahul Sharma

İle değil çalışır mı VectorDrawablessadece sayin öncesi L çalışan tüm cihazlarda. Kullanılacak daha güvenli ve daha doğru API'ler olduğundan bu yanıtı kullanırken dikkatli olun.
Sakiboy

4

Bunun için küçük bir kitaplık tasarladım - metin görünümü açısından zengin çekilebilir (ayrıca bileşik çekilebilir öğelerin boyutunu ve renk tonunu tanımlamayı da destekliyor).

<com.tolstykh.textviewrichdrawable.TextViewRichDrawable
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Some text"
    app:compoundDrawableHeight="24dp"
    app:compoundDrawableWidth="24dp"
    app:drawableTopVector="@drawable/some_vector_drawble"
    app:drawableEndVector="@drawable/another_vector_drawable"
    app:drawableTint="@color/colorAccent" />

Ve bağımlılık

compile 'com.tolstykh.textviewrichdrawable:textview-rich-drawable:0.3.2'

görüntü açıklamasını buraya girin


3

Bağlama kullanıyorsanız, bir TextView'da vektörleri kullanmak için aynı yaklaşıma sahip olmanın başka bir sihirli yolu vardır. Onları şöyle sarmak:

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 sanırım TextView veya benzeri getDrawableyöntemi kullanıyor AppCompatResources.


2

Behzad Bahmanyar'ın cevabına dayanarak, normal png dosyaları için android'in normal özelliklerini kullanamayacağımı fark ettim:

android:drawableTop
android:drawableBottom
etc

çünkü null in ile değiştirilecektir

Drawable drawableTop = null;
...
setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, drawableTop, drawableEnd, drawableBottom);

eğer app:drawableTopCompatset değildi ama android:drawableTop(örn için) idi.

İşte tam çözüm:

public class CustomTextView extends AppCompatTextView {
    private static final int NOT_SET = -1;
    private static final int LEFT = 0;
    private static final int START = 0;
    private static final int TOP = 1;
    private static final int RIGHT = 2;
    private static final int END = 2;
    private static final int BOTTOM = 3;

    public CustomTextView(Context context) {
        super(context);
    }

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initAttrs(context, attrs);
    }

    public CustomTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(context, attrs);
    }

    void initAttrs(Context context, AttributeSet attrs) {
        if (attrs == null) {
            return;
        }
        Drawable[] drawablesArr = getCompoundDrawables();

        TypedArray attributeArray = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView);
        Drawable drawableStart = null;
        Drawable drawableEnd = null;
        Drawable drawableBottom = null;
        Drawable drawableTop = null;
        Drawable drawableLeft = null;
        Drawable drawableRight = null;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            drawableStart = attributeArray.getDrawable(R.styleable.CustomTextView_drawableStartCompat);
            drawableEnd = attributeArray.getDrawable(R.styleable.CustomTextView_drawableEndCompat);
            drawableBottom = attributeArray.getDrawable(R.styleable.CustomTextView_drawableBottomCompat);
            drawableTop = attributeArray.getDrawable(R.styleable.CustomTextView_drawableTopCompat);
            drawableLeft = attributeArray.getDrawable(R.styleable.CustomTextView_drawableLeftCompat);
            drawableRight = attributeArray.getDrawable(R.styleable.CustomTextView_drawableRightCompat);
        } else {
            final int drawableStartId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableStartCompat, NOT_SET);
            final int drawableEndId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableEndCompat, NOT_SET);
            final int drawableBottomId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableBottomCompat, NOT_SET);
            final int drawableTopId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableTopCompat, NOT_SET);
            final int drawableLeftId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableLeftCompat, NOT_SET);
            final int drawableRightId = attributeArray.getResourceId(R.styleable.CustomTextView_drawableRightCompat, NOT_SET);

            if (drawableStartId != NOT_SET)
                drawableStart = AppCompatResources.getDrawable(context, drawableStartId);
            if (drawableLeftId != NOT_SET)
                drawableLeft = AppCompatResources.getDrawable(context, drawableLeftId);
            if (drawableEndId != NOT_SET)
                drawableEnd = AppCompatResources.getDrawable(context, drawableEndId);
            if (drawableRightId != NOT_SET)
                drawableRight = AppCompatResources.getDrawable(context, drawableRightId);
            if (drawableBottomId != NOT_SET)
                drawableBottom = AppCompatResources.getDrawable(context, drawableBottomId);
            if (drawableTopId != NOT_SET)
                drawableTop = AppCompatResources.getDrawable(context, drawableTopId);
        }

        drawableStart = (drawableStart != null ? drawableStart : drawablesArr[START]);
        drawableLeft = (drawableLeft != null ? drawableLeft : drawablesArr[LEFT]);
        drawableStart = (drawableStart != null ? drawableStart : drawableLeft);

        drawableEnd = (drawableEnd != null ? drawableEnd : drawablesArr[END]);
        drawableRight = (drawableRight != null ? drawableRight : drawablesArr[RIGHT]);
        drawableEnd = (drawableEnd != null ? drawableEnd : drawableRight);

        drawableBottom = (drawableBottom != null ? drawableBottom : drawablesArr[BOTTOM]);
        drawableTop = (drawableTop != null ? drawableTop : drawablesArr[TOP]);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStart, drawableTop, drawableEnd, drawableBottom);
        } else {
            setCompoundDrawables(drawableStart, drawableTop, drawableEnd, drawableBottom);
        }

        attributeArray.recycle();
    }
}

Bu cevap kabul edilmelidir. normal png dosyaları ve drawableTop, drawableBottom öznitelikleri ile çalışın. Kabul edilen yanıt png dosyası ve drawableTop, drawableBottom öznitelikleriyle çalışmaz.
Bhargav Pandya

2

Build.gradle (app) dosyasında

android {
    compileSdkVersion 26
    defaultConfig {
        vectorDrawables.useSupportLibrary = true
    }

    dataBinding {
        enabled = true
    }
}

...

public class BindingUtils {
    @BindingAdapter("android:drawableRight")
    public static void setDrawableStart(TextView textView, int resourceId) {
        Drawable drawable = AppCompatResources.getDrawable(textView.getContext(), resourceId);
        Drawable[] drawables = textView.getCompoundDrawables();
        textView.setCompoundDrawablesWithIntrinsicBounds(drawable,
                drawables[1], drawables[2], drawables[3]);
    } 
}

kullan (Veri Bağlarken)

android:drawableRight="@{viewModel.ResId}"

Veya (Normal)

android:drawableRight="@{@drawable/ic_login_24dp}"

1

Vector Drawables kullanımı

KOTLIN

 val drawable1 = VectorDrawableCompat.create(resources, R.drawable.ic_rb_username, theme)
        yourView.setCompoundDrawablesRelativeWithIntrinsicBounds( drawable1, null, null, null)

java

  Drawable drawable1 = VectorDrawableCompat.create(getResources(), R.drawable.ic_rb_username, getTheme());
        yourView.setCompoundDrawablesRelativeWithIntrinsicBounds( drawable1, null, null, null);

1

Geriye dönük uyumluluk için şunları kullanın:

TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, left, top, right, bottom)

0

Bu Sorunu çözmek için Bağlama adaptörü kullanıyorum

@JvmStatic
@BindingAdapter("drawableSvgLeft")
fun addDrawableSvgLeft(textView: TextView,drawable: Drawable){
    textView.setCompoundDrawablesWithIntrinsicBounds(drawable,null,null,null)
}

@JvmStatic
@BindingAdapter("drawableSvgRight")
fun addDrawableSvgRight(textView: TextView,drawable: Drawable){
    textView.setCompoundDrawablesWithIntrinsicBounds(null,null,drawable,null)
}

ve ayrıca düzenimde bu şekilde kullanıyorum

<TextView
  drawableSvgRight="@{@drawable/svg_ic_battle_trophy}"
  .....

muhtemelen vectorDrawables.useSupportLibrary = varsayılan yapılandırmada true gerekli

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.