android : DrawableRight를 사용하여 Buttons 및 TextViews에서 VectorDrawable을 사용할 수 있습니까?


120

Textview 또는 imageview에서 VectorDrawable 자산을 사용할 때 "android : DrawableRight"/ "android : DrawableEnd"/ "android : DrawableStart"/ "android : DrawableLeft"를 사용할 때 런타임 충돌이 발생합니다.

앱은 경고없이 잘 컴파일됩니다.

나는 사용하고있다

  • Gradle 1.5
  • 지원 라이브러리 23.2 ( 'com.android.support:appcompat-v7:23.2.0')

그러나 내가 찾은 것은 이와 같은 충돌없이 Java에서 프로그래밍 방식으로 SVG를 할당 할 수 있다는 것입니다.

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

(나는 이것이 23.2에 대한 지원 라이브러리 버그라고 생각합니다.)

그러나 SVG 자산에 drawableRight 등을 사용할 수 있습니까?

여기 내 레이아웃

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

여기 내 활동

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

        }
    }

다음은 Google의 머티리얼 디자인 사이트에서 수정되지 않은 VectorDrawable 자산입니다.

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

여기 내 앱 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'
}

여기 충돌이 있습니다. (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) 
...

아니요. SVG 파일 은 기본적으로 지원 되지 않으므로 할 수 없습니다 . 대신 VectorDrawable을 사용해야합니다 (SVG 사양의 하위 집합 만 사용).
Phantômaxx

2
drawableLeft, drawableRight, drawableTop, drawableBottom 체크 아웃으로 VectorDrawable를 사용하는 방법을 보려면 이 답변
베 자드 Bahmanyar

나는 이것이 나를 위해 작동
Huy Tower

답변:


186

SVG 자산에 drawableRight 등을 사용할 수 있습니까?

AppCompatTextView는 이제 지지체는 app:drawableLeftCompat, app:drawableTopCompat, app:drawableRightCompat, app:drawableBottomCompat, app:drawableStartCompatapp:drawableEndCompat화합물 드로어 블은 같은 그리기 유형 백 포트지지 VectorDrawableCompat.

이것을 gradle 파일에 포함하십시오.

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

텍스트보기에서 다음을 사용할 수 있습니다.

app:drawableLeftCompat
app:drawableStartCompat

버튼에서 app : drawableLeftCompat, app : drawableStartCompat를 사용하는 동안 문제가 발생하면 라이브러리를 다음으로 업데이트해야합니다.

androidx.appcompat : appcompat : 1.2.0-alpha01

그들은 버그가 있었다

androidx.appcompat : appcompat : 1.1.0-alpha01

당신은 문서를 볼 수 있습니다


또는 아직 업데이트하지 않으려면 다음을 수행하십시오.

Google이이 문제에 대해 조만간 조치를 취하지 않을 것 같기 때문에 모든 앱에 대해보다 견고한 재사용 가능한 솔루션을 찾아야했습니다.

  1. 먼저 앱 "res / values ​​/ attrs.xml" 의 attrs.xml 파일에 사용자 정의 TextView 속성을 추가 하십시오 .

    <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. 그런 다음 다음과 같이 사용자 지정 TextView 클래스를 만듭니다.

    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. 이제 사용자 정의 속성으로 모든 레이아웃에서 쉽게 사용할 수 있습니다.

    <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 -->
        />
    • Button , EditTextRadioButton 은 TextView에서 파생 되었기 때문에 비슷한 작업을 수행 할 수 있습니다.

도움이 되었기를 바랍니다 :)


4
매우 유용한 답변입니다. 어쨌든 Dadou의 매우 완전한 답변 도 읽는 것이 좋습니다 . 그 대답이 나를 위해 일했음을 암시하므로 vectorDrawables { useSupportLibrary = true }내에서 제거 build.gradle하십시오.
Sam

그렇게했고 이제 다음과 같은 문제가 있습니다. XML에서 onclick을 첨부하면 다음 오류가 발생합니다. java.lang.NoSuchMethodException : onClick [class android.view.View]
Ramdane Oualitsen

3
나는 vectorDrawables useSupportLibrary = truegradle 에서 줄을 제거하는 데 동의하지 않습니다. 제거해도 벡터를 뷰 안에 넣을 수는 있지만 png와 같은 방식으로 크기가 조정되어 늘어나고 거칠어집니다. 5.0 / API21 미만의 장치가 실제로 벡터의 크기를 올바르게 조정하여 선명하게 보이게하려면 gradle 파일 내에서 해당 줄을 사용해야합니다. 해당 줄을 넣으면 IDE를 호출하여 벡터를 잘못 사용하는 영역을 찾은 다음 app:srcCompatvia XML을 사용하거나 코드를 통해 설정 해야합니다.VectorDrawableCompat.create()
Heinous Games

app:drawableEndCompat더 나은 RTL 지원 을 위해 추가하는 방법은 무엇입니까? 원인 setCompoundDrawablesRelativeWithIntrinsicBounds은 최소한 API 레벨 17이 필요합니다.
Dr.jacky

1
드로어 블을 프로그래밍 방식으로 설정하는 것은 어떻습니까?
안드로이드 개발자

77

이 솔루션은 더 이상 올바르지 않습니다. 23.3.0 버전부터 벡터 드로어 블은 app : srcCompat 또는 setImageResource ()를 통해서만로드 할 수 있습니다.

벡터 드로어 블을 레이어 목록 또는 선택기로 래핑합니다.

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

이것은 잘 작동합니다. 감사합니다 ..하지만 "android : drawableXXXXX"에서 SVG를 직접 참조 할 수없는 것 같습니다. 다른 것으로 감싸 야합니다.
angryITguy

1
예. 직접 사용할 수 없습니다. app : srcCompat 또는 래핑 또는 프로그래밍 방식으로 만 가능합니다. 이것은 여기에 설명했다 : android-developers.blogspot.ru/2016/02/...
알렉산드르 Shutko 씨가

아 .. 고마워 .. 말씀하신 내용이 보이네요. 그래서, 그들이 당신에게 그것을하지 말라고 말한다면 그것은 여전히 ​​버그입니까? )
angryITguy

1
나는 그것이 모두 이전 버전과의 호환성에 관한 것이라고 생각합니다. 전체 SVG 지원을받을 수있는 몇 가지 문제가있는 것처럼 그들이 ... 몇 가지 해결 방법을했다, 그래서 보이는
알렉산드르 Shutko 씨

2
지원 버전 23.3.0의 @HarishGyanani는 더 이상 지원되지 않습니다. 활동에 더 많은 명령을 추가해야합니다. static {if (Build.VERSION.SDK_INT <Build.VERSION_CODES.LOLLIPOP) {AppCompatDelegate.setCompatVectorFromResourcesEnabled (true); }}
쿠옹 응우 엔

75

내가 찾은 가장 좋은 방법 :

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

9
8/25/17 현재 이것은 나에게 적합한 유일한 것입니다 (프로그래밍 방식으로 드로어 블 설정). 나는 실제로 사용 :Drawable drawable = VectorDrawableCompat.create(getResources(), status.getIconResId(), wrapper.getTheme()); statusButton.setCompoundDrawablesRelativeWithIntrinsicBounds(null, drawable, null, null);
saiyancoder

2
minSdk setCompoundDrawablesWithIntrinsicBounds17 입니다. 그렇지 않으면 이것은 잘 작동합니다.
Victor Rendina 2017

1
minSdk는 17이 아니라 1이며 아마도 비슷한 API를 볼 수 있습니다. setCompoundDrawablesWithIntrinsicBounds => minSdk 1; setCompoundDrawablesRelativeWithIntrinsicBounds => minSdk 17
正宗白布鞋

프로그래밍 방식 설정을위한 최상의 솔루션, +1
Woton Sampaio

나는 이것을 BindingAdapters와 함께 사용했으며 효과적으로 작동합니다. 감사합니다!
Ric17101

61

여기에 대한 답변 중 일부를 보완하려면 VectorDrawable을 drawableLeft(등)으로 사용할 수 있지만 지원 라이브러리 버전에 따라 다르며 가격이 제공됩니다.

어떤 경우에 작동합니까? 도움을주기 위해이 다이어그램 을 만들었습니다 (지원 라이브러리 23.4.0에서 최소-25.1.0까지 유효 함).

VectorDrawable 치트 시트


2
그것은 위대한하지만 당신은 정적 블록에 메소드 이름을 수정해야합니다setCompatVectorFromResourcesEnabled
카스 Patidar

1
솔루션은 불행하게도, 25.3.1에서 작동하지 않습니다 setCompatVectorFromResourcesEnabled
Ilja S.

From 23.3.0 version vector drawables can only be loaded via app:srcCompat or setImageResource()
따라서이

활성화 setCompatVectorFromSourcesEnabled(true)하면 android:backgroundAndroid 4.x 에서 벡터 드로어 블을로드 할 수 있습니다 . 감사합니다! (실제 벡터를 단일 항목 레이어 목록으로 래핑해야합니다.)
Peterdk

14

다른 답변은 효과가 없었습니다. 여기에 a VectorDrawable를 추가 한 방법 이 있습니다 . 아래를 다룰 때 TextView사용해야 합니다 .VectorDrawableCompat.create()VectorDrawablesAndroid 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);
}

짧고, 달콤하고, 요점!


이것은 Android P 및 최소 API 레벨 26 (목표 28)에서 작동했습니다
MiStr

@MiStr-이전 버전과도 호환됩니다. :)
Sakiboy

9

Google에서 : Android 지원 라이브러리 23.3.0부터 지원 벡터 드로어 블은 app : srcCompat 또는 setImageResource ()를 통해서만로드 할 수 있습니다.

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


1
즉, 지금은 해결책 없습니다
킬러

벡터 드로어 블을 레이어 목록 또는 선택기로 래핑합니다. <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 = " schemas .android.com / apk / res / android "> <item android : drawable ="@ drawable / ic_accessible_white_36px "/> </ layer-list>
Null 포인터 예외

9

xml에서 벡터 드로어 블을 직접 설정할 수 있지만 데이터 바인딩 프레임 워크가 포함되어 있습니다.

그냥 써

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

전체 레이아웃을 <layout>태그로 래핑 하므로 기본적으로 xml은 다음과 같습니다.

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

데이터 바인딩 프레임 워크를 활성화하려면

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

바인딩 라이브러리의 다른 기능을 사용할 필요가 없습니다.

편집하다:

물론 Lollipop 이전에 벡터 드로어 블을 사용하려면 다음을 사용하여 벡터 드로어 블을 지원해야합니다.

vectorDrawables.useSupportLibrary = true

따라서 build.gradle두 가지 새로운 명령이 필요합니다.

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

발언에 대한 rkmax 에게 감사드립니다


이것은 좋은 생각이지만 이것이 작동하려면 바인딩 어댑터를 작성해야합니다. 다음은 작동하는 예입니다. gist.github.com/lisawray/78c33f76809d2bcbbec9983e2c141a70
BladeCoder

1
나는 이것이 나를 위해 작동한다고 말해야하지만 당신은 vectorDrawables.useSupportLibraryapp / build.gradle 에서 활성화 하고 또한 활동에 AppCompatDelegate.setCompatVectorFromResourcesEnabled (true)를 추가해야합니다
rkmax

나는 build.gradle그것이 작동하지 않는 이유 일 수있는 defaultConfig를 추가하는 것을 잊었다
Hans M

고마워요-당신은 생명의 은인입니다!
Van

이것은 과소 평가 된 답변입니다!
DYS

6

모든 답변을 살펴보고 최신 Android 스튜디오 3.0.1 및 AppCompat 지원 라이브러리 26.1.0을 사용하여 제대로 작동한다고 확신 할 수 있습니다.

에서 build.gradle (응용 프로그램) 파일

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

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

그리고 활동 확장 AppcompatActivity에는이 외부 방법 즉 static블록 이 포함됩니다.

static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}  

또는 이것이 전체 앱에 적용되도록하려면 클래스 확장 Application클래스 안에이 줄을 포함하면됩니다.

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

XML의 Textview

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

어떤 API에서 잘 작동합니까? 19 번이나 20 번 입어 보셨나요?
Divers

XML에서 drawableRightfor TextView를 어떻게 사용하는지 보여줄 수 있습니까 ?
Divers

2
위에서 언급 한 몇 가지와 같이 벡터 xml을 drawableLeft로 직접 사용하면 여전히이 충돌 또는 예외가 발생하므로 해결 방법은 해당 벡터 xml을 Textview의 drawableLeft에 대한 선택기로 사용하는 것입니다. 사용법 u는 편집 된 답변에서 볼 수 있습니다.
Amit Tumkur

1
작동하지 않을 것입니다. xml에서 직접 TextView에 벡터 드로어 블을 사용할 수 없습니다
user25

API 19 및 20에서 테스트합니다. 대신 응용 프로그램 클래스에서 AppCompatDelegate.setCompatVectorFromResourcesEnabled를 사용했습니다. 매력처럼 작동!
Red M


5

나는이 문제에 늦게 붙어서이 질문에 답하기에는 너무 늦었습니다. TextView와 함께 svg / vector 드로어 블과 동일한 문제가 발생했습니다. 사용자 정의 드로어 블을 만드는 대신 아래와 같이 두 줄의 코드로 문제를 해결할 수 있습니다.

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

도움이되기를 바랍니다.


사전 L장치 와 호환되지 않습니다 .
Sakiboy

나는 최소 API (17)이 코드를 사용하고 같은 @Sakiboy 그래 그것은이다
라훌 샤르마을

VectorDrawablespre-L을 실행하는 모든 장치에서 작동하지 않습니다 . 더 안전하고 정확한 API를 사용할 수 있으므로이 답변을 사용할 때주의하십시오.
Sakiboy

4

나는 이것을 위해 작은 라이브러리를 디자인했습니다 -textview-rich-drawable (복합 드로어 블의 크기와 색조 정의도 지원합니다).

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

그리고 의존성

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

여기에 이미지 설명 입력


3

바인딩을 사용하는 경우 TextView에서 벡터를 사용하는 것과 동일한 방법을 사용하는 또 다른 마법의 방법이 있습니다. 다음과 같이 포장합니다.

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

그것은 마술처럼 작동 할 것입니다. 뒤에서 무슨 일이 일어나고 있는지 조사하지 않았지만 TextView가 또는 비슷한 getDrawable방법을 사용하고 있다고 생각합니다 AppCompatResources.


2

Behzad Bahmanyar의 답변 에 따라 일반 png 파일에 Android의 일반 속성을 사용할 수 없음을 알았습니다.

android:drawableTop
android:drawableBottom
etc

null로 대체되기 때문에

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

app:drawableTopCompat설정되지 않은 경우android:drawableTop (예 :)

다음은 전체 솔루션입니다.

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

이것은 받아 들여진 대답이어야합니다. 일반적인 png 파일 및 속성 drawableTop, drawableBottom. 허용되는 답변은 png 파일 및 drawableTop, drawableBottom 속성에서 작동하지 않습니다.
Bhargav Pandya

2

build.gradle (앱) 파일

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

사용 (데이터 바인딩시)

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

또는 (일반)

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

1

벡터 드로어 블 사용 사용

Kotlin

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

자바

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

1

이전 버전과의 호환성을 위해 :

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

0

이 문제를 해결하기 위해 바인딩 어댑터를 사용하고 있습니다.

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

내 레이아웃에서도 이런 식으로 사용

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

아마도 vectorDrawables.useSupportLibrary = true 기본 구성이 필요합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.