Apakah mungkin menggunakan VectorDrawable di Buttons dan TextView menggunakan android: DrawableRight?

120

Saat saya menggunakan aset VectorDrawable dalam textview atau imageview, saya mengalami error runtime saat menggunakan "android: DrawableRight" / "android: DrawableEnd" / "android: DrawableStart" / "android: DrawableLeft".

Aplikasi akan mengkompilasi dengan baik tanpa peringatan apa pun.

saya menggunakan

  • Gradle 1.5
  • Pustaka Dukungan 23.2 ('com.android.support:appcompat-v7:23.2.0')

Apa yang saya temukan adalah bahwa saya dapat menetapkan SVG secara terprogram di Java tanpa crash seperti ini.

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

(Saya menduga ini adalah bug pustaka dukungan untuk 23.2.)

Tetapi apakah mungkin menggunakan drawableRight dll untuk aset SVG?

Ini tata letak saya

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

Inilah Aktivitas saya

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

        }
    }

Berikut adalah aset VectorDrawable yang tidak dimodifikasi dari situs desain material Google.

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

Ini adalah aplikasi saya 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'
}

Ini kecelakaannya. (Perhatikan kesalahan pemekaran yang mereferensikan textview.)

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) 
...
angryITguy
sumber
Tidak, Anda tidak bisa, karena file SVG tidak didukung secara native . Anda harus menggunakan VectorDrawable, sebagai gantinya (yang hanya menggunakan subset spesifikasi SVG).
Phantômaxx
2
Untuk melihat bagaimana menggunakan VectorDrawable dengan drawableLeft, drawableRight, drawableTop, drawableBottom lihat Jawaban ini
Behzad Bahmanyar
Saya menemukan ini berfungsi untuk saya: android.jlelse.eu/…
Huy Tower

Jawaban:

186

apakah mungkin untuk menggunakan drawableRight dll untuk aset SVG?

Iya

AppCompatTextView sekarang mendukung app:drawableLeftCompat, app:drawableTopCompat, app:drawableRightCompat, app:drawableBottomCompat, app:drawableStartCompatdan app:drawableEndCompatdigambar majemuk, pendukung yang backported jenis ditarik seperti VectorDrawableCompat.

Sertakan ini dalam file gradle Anda

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

Dalam tampilan teks Anda, Anda dapat menggunakan

app:drawableLeftCompat
app:drawableStartCompat

Jika Anda mengalami masalah saat menggunakan app: drawableLeftCompat, app: drawableStartCompat di tombol, Anda perlu memperbarui pustaka ke

androidx.appcompat: appcompat: 1.2.0-alpha01

mereka memiliki bug

androidx.appcompat: appcompat: 1.1.0-alpha01

Anda dapat melihat dokumennya


Atau jika Anda belum ingin memperbarui, maka:

Karena tampaknya Google tidak akan melakukan apa pun terkait masalah ini dalam waktu dekat, saya harus menemukan solusi yang lebih solid yang dapat digunakan kembali untuk semua aplikasi saya:

  1. Pertama tambahkan atribut TextView kustom di file attrs.xml aplikasi Anda "res / values ​​/ attrs.xml" :

    <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. Kemudian buat kelas TextView kustom seperti ini:

    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. Sekarang Anda dapat menggunakannya dengan mudah di tata letak apa pun dengan atribut khusus Anda:

    <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 -->
        />
    
    • Anda dapat melakukan hal serupa dengan Button , EditText dan RadioButton karena mereka berasal dari TextView

Semoga ini membantu :)

Behzad Bahmanyar
sumber
4
Jawaban yang sangat berguna. Bagaimanapun, saya merekomendasikan membaca jawaban Dadou yang sangat lengkap juga. Menghapus vectorDrawables { useSupportLibrary = true }dari build.gradlejawaban saya karena saran itu berhasil untuk saya.
Sam
Saya melakukan itu dan sekarang saya memiliki masalah berikut: ketika saya memasang onclick dalam XML saya mendapatkan kesalahan berikut: java.lang.NoSuchMethodException: onClick [class android.view.View]
Ramdane Oualitsen
3
Saya tidak setuju dengan penghapusan vectorDrawables useSupportLibrary = truegaris dari gradle. Saat Anda menghapusnya, Anda masih bisa meletakkan vektor di dalam tampilan Anda, tetapi mereka mengubah ukurannya dengan cara yang sama seperti png, yang berarti vektor akan melebar dan menjadi berbintik. Jika Anda ingin perangkat di bawah 5.0 / API21 benar-benar mengubah ukuran vektor dengan benar sehingga terlihat tajam, Anda harus menggunakan baris itu di dalam file gradle. Menempatkan baris itu memanggil IDE untuk menemukan area di mana Anda menggunakan vektor secara tidak benar dan kemudian Anda harus menggunakan app:srcCompatvia XML atau mengaturnya melalui kode denganVectorDrawableCompat.create()
Heinous Games
Bagaimana cara menambahkan app:drawableEndCompatuntuk dukungan RTL yang lebih baik? Penyebab setCompoundDrawablesRelativeWithIntrinsicBoundsmembutuhkan setidaknya API level 17.
Dr. jacky
1
Bagaimana dengan menyetel drawable secara terprogram?
Pengembang android
77

Solusi ini tidak lagi tepat. Dari sumber daya dapat digambar versi 23.3.0 hanya dapat dimuat melalui app: srcCompat atau setImageResource ()

Cobalah untuk menggabungkan drawable vektor Anda ke dalam daftar lapisan atau selektor:

<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>
Alexandr Shutko
sumber
Ini bekerja dengan baik. Terima kasih .. Tapi tampaknya Anda tidak bisa langsung merujuk ke SVG di "android: drawableXXXXX", Anda harus membungkusnya dengan sesuatu yang lain.
angryITguy
1
Iya. Anda tidak dapat menggunakannya secara langsung. Hanya sebagai app: srcCompat atau dibungkus atau secara terprogram. Ini dijelaskan di sini: android-developers.blogspot.ru/2016/02/…
Alexandr Shutko
Ahh .. terima kasih .. Saya bisa melihat paragraf yang Anda maksud. Jadi, apakah masih bug jika mereka menyuruh Anda untuk tidak melakukannya? ;)
angryITguy
1
Saya pikir ini semua tentang kompatibilitas ke belakang. Sepertinya ada masalah untuk mendapatkan dukungan penuh svg, jadi mereka membuat beberapa solusi ...
Alexandr Shutko
2
@HarishGyanani dari versi dukungan 23.3.0, tidak ada lagi dukungan. Anda harus menambahkan lebih banyak perintah dalam aktivitas Anda: static {if (Build.VERSION.SDK_INT <Build.VERSION_CODES.LOLLIPOP) {AppCompatDelegate.setCompatVectorFromResourcesEnabled (true); }}
Cuong Nguyen
75

Cara terbaik yang saya temukan:

Drawable leftDrawable = AppCompatResources.getDrawable(this, R.drawable.ic_search);
search.setCompoundDrawablesWithIntrinsicBounds(leftDrawable, null, null, null);
Hani
sumber
9
Mulai 25/8/17, ini adalah satu-satunya hal yang berfungsi untuk saya (menyetel drawable secara terprogram). Saya sebenarnya menggunakan:Drawable drawable = VectorDrawableCompat.create(getResources(), status.getIconResId(), wrapper.getTheme()); statusButton.setCompoundDrawablesRelativeWithIntrinsicBounds(null, drawable, null, null);
saiyancoder
2
minSdk untuk setCompoundDrawablesWithIntrinsicBoundsadalah 17 . Jika tidak, ini bekerja dengan baik.
Victor Rendina
1
MinSdk-nya adalah 1 bukan 17, Anda mungkin terlihat seperti apis. setCompoundDrawablesWithIntrinsicBounds => minSdk 1; setCompoundDrawablesRelativeWithIntrinsicBounds => minSdk 17
正宗 白 布鞋
Solusi terbaik untuk pengaturan programatis, +1
Woton Sampaio
Saya menggunakan ini dengan BindingAdapters dan bekerja secara efektif, terima kasih!
Ric17101
61

Untuk melengkapi beberapa jawaban di sini: Anda bisa membuat VectorDrawable berfungsi sebagai drawableLeft(dll.) Tetapi itu bergantung pada versi Pustaka Dukungan dan ada harganya.

Dalam kasus apa ini berhasil? Saya telah membuat diagram ini untuk membantu (berlaku untuk Support Library 23.4.0 hingga - setidaknya - 25.1.0).

Cheatsheet VectorDrawable

David Ferrand
sumber
2
Ini bagus tetapi Anda harus memperbaiki nama metode dalam blok statis menjadisetCompatVectorFromResourcesEnabled
Vikas Patidar
1
solusi setCompatVectorFromResourcesEnabled tidak berfungsi pada 25.3.1, sayangnya
Ilja S.
From 23.3.0 version vector drawables can only be loaded via app:srcCompat or setImageResource()jadi solusi ini sudah usang dan tidak akan berfungsi
pengguna25
mengaktifkan setCompatVectorFromSourcesEnabled(true)memungkinkan untuk memuat vectordrawables di android:backgroundAndroid 4.x. Jadi terima kasih! (Anda memang perlu membungkus vektor sebenarnya dalam satu daftar lapisan item)
Peterdk
14

Tidak ada jawaban lain yang berfungsi, berikut cara saya menambahkan a VectorDrawableke a TextView, yang harus Anda gunakan VectorDrawableCompat.create()saat menangani di VectorDrawablesbawah ini 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);
}

Singkat, manis, dan langsung ke sasaran!

Sakiboy
sumber
Ini berfungsi untuk Android P, dan min API level 26 (target 28)
MiStr
@MiStr - Ini juga kompatibel ke belakang :)
Sakiboy
9

Dari Google: Mulai Android Support Library 23.3.0, dukungan vector drawable hanya dapat dimuat melalui app: srcCompat atau setImageResource () ..

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

paulzeng
sumber
1
itu berarti tidak ada solusi untuk saat ini
Pembunuh
Cobalah untuk menggabungkan drawable vektor Anda ke dalam daftar lapisan atau pemilih: <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 = " skema .android.com / apk / res / android "> <item android: drawable =" @ drawable / ic_accessible_white_36px "/> </layer-list>
Pengecualian Pointer Null
9

Anda dapat langsung menyetel vector drawable dalam xml, tetapi Anda telah menyertakan framework data binding.

Tulis saja

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

dan membungkus seluruh tata letak Anda dalam sebuah <layout>tag, jadi pada dasarnya xml Anda akan terlihat seperti:

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

Untuk mengaktifkan kerangka data binding cukup tambahkan

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

Anda tidak perlu menggunakan fitur lain dari library binding

EDIT:

Tentu saja jika Anda ingin menggunakan vector drawable sebelum Lollipop Anda harus mengaktifkan dukungan vector drawable menggunakan

vectorDrawables.useSupportLibrary = true

Jadi Anda build.gradlemembutuhkan 2 perintah baru:

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

terima kasih kepada rkmax untuk komentarnya

Hans M
sumber
Ini ide yang bagus, tetapi Anda perlu menulis adaptor pengikat agar ini berfungsi. Berikut adalah contoh yang berfungsi: gist.github.com/lisawray/78c33f76809d2bcbbec9983e2c141a70
BladeCoder
1
Saya harus mengatakan ini berfungsi untuk saya tetapi Anda harus mengaktifkannya vectorDrawables.useSupportLibrarydi app / build.gradle dan juga menambahkan AppCompatDelegate.setCompatVectorFromResourcesEnabled (true) pada aktivitas
rkmax
Saya lupa menambahkan defaultConfig build.gradleyang mungkin menjadi alasan mengapa tidak berfungsi
Hans M
Terima kasih - Anda adalah penyelamat hidup!
Van
Ini adalah jawaban yang diremehkan!
DYS
6

Saya memeriksa semua jawaban dan menggunakan Android studio 3.0.1 dan AppCompat Support Library 26.1.0 terbaru. Saya dapat memastikan ini berfungsi dengan baik.

Dalam file build.gradle (app)

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

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

Dan dalam Kegiatan memperluas AppcompatActivitytermasuk metode luar ini yaitu satu staticblok

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}  

atau jika Anda ingin ini diterapkan ke seluruh aplikasi cukup sertakan baris ini di dalam kelas yang memperluas Applicationkelas

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

Textview dalam xml

<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>
Amit Tumkur
sumber
Berfungsi dengan baik pada API apa? Apakah Anda mencoba pada 19 atau 20?
Penyelam
Dapatkah Anda menunjukkan bagaimana Anda menggunakan drawableRightuntuk TextViewdi XML?
Penyelam
2
seperti beberapa yang disebutkan di atas, jika Anda menggunakan vektor xml secara langsung sebagai drawableLeft, Anda masih mengalami crash atau pengecualian ini, maka solusinya adalah menggunakan vektor itu xml sebagai pemilih untuk drawableLeft untuk Textview. Penggunaan yang bisa Anda lihat di jawaban yang diedit.
Amit Tumkur
1
itu tidak akan berhasil, Anda tidak dapat menggunakan drawable vektor untuk TextView secara langsung di xml
pengguna25
Mengujinya di API 19, dan 20. Saya menggunakan AppCompatDelegate.setCompatVectorFromResourcesEnabled di kelas aplikasi sebagai gantinya. Bekerja seperti pesona!
Red M
5

Saya sangat terlambat untuk menjawab pertanyaan ini karena saya terlambat mengatasi masalah ini. Saya memiliki masalah yang sama dengan drawable svg / vektor dengan TextView. Alih-alih membuat drawable khusus Anda sendiri, saya dapat memperbaiki masalah saya dengan 2 baris kode seperti di bawah ini:

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

Semoga ini akan membantu Anda.

Rahul Sharma
sumber
Tidak kompatibel dengan Lperangkat pra .
Sakiboy
@Sakiboy Ya, karena saya menggunakan kode ini dengan api minimum 17.
Rahul Sharma
Tidak bekerja dengan VectorDrawablessemua perangkat yang menjalankan pra-L, katakan saja. Berhati-hatilah saat menggunakan jawaban ini, karena ada API yang lebih aman dan lebih akurat untuk digunakan.
Sakiboy
4

Saya telah merancang pustaka kecil untuk ini - textview-rich-drawable (ini juga mendukung penentuan ukuran dan pewarnaan yang dapat digambar majemuk).

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

Dan ketergantungan

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

masukkan deskripsi gambar di sini

Oleksandr
sumber
3

Jika Anda menggunakan binding, ada cara ajaib lain untuk memiliki pendekatan yang sama untuk menggunakan vektor dalam TextView. Membungkusnya seperti:

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 kira TextView menggunakan getDrawablemetode dari AppCompatResourcesatau serupa.

cesards
sumber
2

Berdasarkan jawaban Behzad Bahmanyar , saya perhatikan bahwa saya tidak dapat menggunakan atribut normal android untuk file png normal:

android:drawableTop
android:drawableBottom
etc

karena akan diganti dengan null in

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

jika app:drawableTopCompattidak ditetapkan, tetapi android:drawableTop(untuk misalnya).

Inilah solusi lengkapnya:

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();
    }
}
Goran Horia Mihail
sumber
Ini harus menjadi jawaban yang diterima. bekerja dengan file png normal dan atribut drawableTop, drawableBottom. Jawaban yang diterima tidak berfungsi dengan file png dan drawableTop, atribut drawableBottom.
Bhargav Pandya
2

Dalam file build.gradle (app)

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

gunakan (Saat Penyatuan Data)

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

Atau (Normal)

android:drawableRight="@{@drawable/ic_login_24dp}"
Ahmad Aghazadeh
sumber
1

Menggunakan penggunaan Vector Drawable

kotlin

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

Jawa

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

Untuk penggunaan kompatibilitas mundur:

TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(textView, left, top, right, bottom)
Shayan_Aryan
sumber
0

Saya menggunakan adaptor Binding untuk memecahkan Masalah ini

@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)
}

dan juga menggunakan cara ini dalam tata letak saya

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

mungkin vectorDrawables.useSupportLibrary = true dalam konfigurasi default diperlukan

mahdi ZTD
sumber