Android Studio에서 벡터 자산의 채우기 색상 변경


169

Android Studio는 이제 21+에서 벡터 자산을 지원하며 컴파일시 더 낮은 버전의 png를 생성합니다. 채우기 색상을 변경하려는 머티리얼 아이콘의 벡터 자산이 있습니다. 이것은 21+에서 작동하지만 생성 된 png는 색상이 변경되지 않습니다. 이것을 할 수있는 방법이 있습니까?

<vector android:height="48dp" android:viewportHeight="24.0"
android:viewportWidth="24.0" android:width="48dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/primary" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>

답변:


333

벡터 자산을 직접 편집하지 마십시오. ImageButton에서 벡터 드로어 블을 사용하는 경우에서 색상을 선택하십시오 android:tint.

<ImageButton
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:id="@+id/button"
        android:src="@drawable/ic_more_vert_24dp"
        android:tint="@color/primary" />

24
틴팅은 21+ 기기에서만 작동합니다. 롤리팝 이전 기기에 대한 제안이
있으십니까

12
android : tint는 APIv1 이후의 모든 Android 버전에서 작동합니다. 당신이 의미하는 것은 drawableTint입니다.
YYYY-MM-DD

31
android:tint다음에 와야합니다android:src
EmmanuelMess

5
어떤 약 drawableLeftButton?
Pratik Butani

8
@mudit은 fillColor = "# colorvalue"로 벡터를 사용하려고 시도합니다. @ 색상 참조는 벡터에 대해 SDK 21+ 만 작동하므로 생성 된 PNG에는 적합하지 않으므로 @ 색상 참조를 사용하지 마십시오.
PieterAelse

95

넌 할 수있어.

그러나 색상 (..lame)에 @color 참조를 사용할 수는 없습니다.

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
    android:viewportHeight="24.0">
<path
    android:fillColor="#FFAABB"
    android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zm-6,0C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>


11
이것이 정답입니다! @ 컬러 참조는 롤리팝 이전의 벡터 (그래서 벡터-> PNG 변환)에서 작동하지 않습니다. code.google.com/p/android/issues/detail?id=186431
PieterAelse

5
@color 참조는 이제 모든 Android 버전의 fillColor 속성에 사용할 수 있지만 색상 상태 목록은 지원하지 않습니다.
TheIT

벡터 상태 목록을 수행하는 방법은 AnimatedStateListDrawable s
gMale을 사용하는 것 같습니다. gMale

1
@TheIT 어떻게 활성화해야합니까? 나를 위해 작동하지 않는 것
urSus

@PieterAelse 확실하지 않습니다. 동일한 자산을 사용하고 싶지만 다른 배경을 가진 경우 (이전 답변과 같은 색조). 솔루션에는 리소스가 동일하지만 채우기 색상이 다른 여러 인스턴스가 있습니다.
Anton Makov

71

다른 답변에서 언급했듯이 벡터 드로어 블을 직접 편집하지 마십시오. 대신 자바 코드로 색조를 지정할 수 있습니다.

    mWrappedDrawable = mDrawable.mutate();
    mWrappedDrawable = DrawableCompat.wrap(mWrappedDrawable);
    DrawableCompat.setTint(mWrappedDrawable, mColor);
    DrawableCompat.setTintMode(mWrappedDrawable, PorterDuff.Mode.SRC_IN);

그리고 단순화를 위해 도우미 클래스를 만들었습니다.

import android.content.Context;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.annotation.ColorRes;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageView;

/**
 * {@link Drawable} helper class.
 *
 * @author Filipe Bezerra
 * @version 18/01/2016
 * @since 18/01/2016
 */
public class DrawableHelper {
    @NonNull Context mContext;
    @ColorRes private int mColor;
    private Drawable mDrawable;
    private Drawable mWrappedDrawable;

    public DrawableHelper(@NonNull Context context) {
        mContext = context;
    }

    public static DrawableHelper withContext(@NonNull Context context) {
        return new DrawableHelper(context);
    }

    public DrawableHelper withDrawable(@DrawableRes int drawableRes) {
        mDrawable = ContextCompat.getDrawable(mContext, drawableRes);
        return this;
    }

    public DrawableHelper withDrawable(@NonNull Drawable drawable) {
        mDrawable = drawable;
        return this;
    }

    public DrawableHelper withColor(@ColorRes int colorRes) {
        mColor = ContextCompat.getColor(mContext, colorRes);
        return this;
    }

    public DrawableHelper tint() {
        if (mDrawable == null) {
            throw new NullPointerException("É preciso informar o recurso drawable pelo método withDrawable()");
        }

        if (mColor == 0) {
            throw new IllegalStateException("É necessário informar a cor a ser definida pelo método withColor()");
        }

        mWrappedDrawable = mDrawable.mutate();
        mWrappedDrawable = DrawableCompat.wrap(mWrappedDrawable);
        DrawableCompat.setTint(mWrappedDrawable, mColor);
        DrawableCompat.setTintMode(mWrappedDrawable, PorterDuff.Mode.SRC_IN);

        return this;
    }

    @SuppressWarnings("deprecation")
    public void applyToBackground(@NonNull View view) {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            view.setBackground(mWrappedDrawable);
        } else {
            view.setBackgroundDrawable(mWrappedDrawable);
        }
    }

    public void applyTo(@NonNull ImageView imageView) {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        imageView.setImageDrawable(mWrappedDrawable);
    }

    public void applyTo(@NonNull MenuItem menuItem) {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        menuItem.setIcon(mWrappedDrawable);
    }

    public Drawable get() {
        if (mWrappedDrawable == null) {
            throw new NullPointerException("É preciso chamar o método tint()");
        }

        return mWrappedDrawable;
    }
}

사용하려면 다음을 수행하십시오.

    DrawableHelper
            .withContext(this)
            .withColor(R.color.white)
            .withDrawable(R.drawable.ic_search_24dp)
            .tint()
            .applyTo(mSearchItem);

또는:

    final Drawable drawable = DrawableHelper
            .withContext(this)
            .withColor(R.color.white)
            .withDrawable(R.drawable.ic_search_24dp)
            .tint()
            .get();

    actionBar.setHomeAsUpIndicator(drawable);

안녕하세요 Filipe, 답변 주셔서 감사합니다. 라이센스를 볼 수있는 라이브러리, 코드 스니핑 코드 github이 있습니까? 고마워 :)
Vincent D.

2
아뇨 Vicent, 라이센스가 전혀 없습니다. 해결책 너무 간단해서 여기에 사용 된 빌더 패턴이 필요하지 않은 것 같습니다. 그러나 누구나이 솔루션의 이점을 누리고 라이센스없이 사용할 수 있습니다.
Filipe Bezerra de Sousa 1

좋은 답변입니다! 내가 원하는대로 작동
Eoin

1
@VincentD. SO 웹 페이지 바닥 글에 "
귀하의

그것은 약간의 변화로 나를 위해 일했습니다. 도와 주셔서 감사합니다.
André Luiz Reis

36

벡터 이미지 색상을 변경하려면 android : tint = "@ color / colorAccent"를 직접 사용할 수 있습니다 .

<ImageView
        android:id="@+id/ivVectorImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_account_circle_black_24dp"
        android:tint="@color/colorAccent" />

프로그래밍 방식으로 색상을 변경하려면

ImageView ivVectorImage = (ImageView) findViewById(R.id.ivVectorImage);
ivVectorImage.setColorFilter(getResources().getColor(R.color.colorPrimary));

getColor () 지원 중단됨
David

TextView의 drawable에 사용하는 방법 ***?
Hemant Kaushik

getColor (ResId)는 @David가 더 이상 사용되지 않지만 getColor(ResId, Theme)그렇지 않습니다. 또는 ResourcesCompat.getColor(getResources(), R.color.primary, null);테마에 관심이없는 경우 또는 컨텍스트 / 정책 대리인이 활동 인 경우 getTheme()마지막 매개 변수에 대해 수행 할 수 있습니다 .
Martin Marconcini

15

현재 작업중인 soloution은 android : fillColor = "# FFFFFF"입니다.

벡터에서 하드 코딩을 제외하고는 아무것도 효과가 없었습니다.

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24.0"
      android:fillColor="#FFFFFF"
    android:viewportHeight="24.0">
<path
    android:fillColor="#FFFFFF"
    android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zm-6,0C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>

그러나 fillcolor 및 tint가 곧 작동 할 수 있습니다. 자세한 내용은이 토론을 참조하십시오.

https://code.google.com/p/android/issues/detail?id=186431

또한 색상 mighr이 캐시에 붙어 있으므로 모든 사용자의 앱을 삭제하면 도움이 될 수 있습니다.


7

Android 스튜디오는 이제 롤리팝 사전 벡터를 지원합니다. PNG 변환이 없습니다. 여전히 채우기 색상을 변경할 수 있으며 작동합니다.

당신이 ImageView에서

 app:srcCompat="@drawable/ic_more_vert_24dp"

gradle 파일에서

 // Gradle Plugin 2.0+  
 android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
   }  
 }  

 compile 'com.android.support:design:23.4.0'

10
문제는 "벡터 자산을 사용하는 방법"이 아니라 "벡터 채우기 색상을 변경하는 방법"입니다.
Leo Droidcoder

5

업데이트 : AppCompat지원

android:tint21 개 이상의 장치에서만 작동 하는지 의심되는 다른 답변 에서는 AppCompat ( v23.2.0 이상 ) 에서 색조 속성의 하위 호환성을 제공합니다.

따라서 조치 과정 은 (Android 네임 스페이스) 대신 AppCompatImageViewapp:srcCompat(AppCompat 네임 스페이스에서)를 사용하는 것입니다 android:src.

다음은 예입니다 (AndroidX : 이것은 androidx.appcompat.widget.AppCompatImageView ;).

<android.support.v7.widget.AppCompatImageView
        android:id="@+id/credits_material_icon"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="16dp"
        android:layout_marginStart="16dp"
        android:scaleType="fitCenter"
        android:tint="#ffd2ee"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:srcCompat="@drawable/ic_dollar_coin_stack" />

그리고 gradle에서 벡터 드로어 블 지원을 활성화하는 것을 잊지 마십시오.

vectorDrawables.useSupportLibrary = true 

그냥 업데이트. 요즘 AppCompatImageView은 아래에 있습니다androidx.appcompat.widget.AppCompatImageView
Roc Boronat

2

이 라이브러리를 Gradle에 추가하여 오래된 Android 장치에서 색 벡터 드로어 블을 활성화하십시오.

compile 'com.android.support:palette-v7:26.0.0-alpha1'

gradle을 다시 동기화하십시오. 나는 그것이 문제를 해결할 것이라고 생각한다.


2

fillColor를 사용하여 벡터가 개별적으로 설정된 색상을 표시하지 않으면 기본 위젯 매개 변수로 설정되었을 수 있습니다.

app:itemIconTint="@color/lime"위젯 아이콘의 기본 색상 유형을 설정하려면 activity_main.xml에 추가하십시오 .

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:itemIconTint="@color/lime"
        app:menu="@menu/activity_main_drawer" />

</android.support.v4.widget.DrawerLayout>

VectorDrawable @ 개발자. 안드로이드


Android 스튜디오 3.6에서 svg xml 변경 : android : fillColor = "# FFFFC400"
a_subscriber

1

이전 버전의 사전 롤리팝을 지원하려는 경우

약간의 변경 사항으로 동일한 XML 코드를 사용하십시오.

정상 대신 ImageView --> AppCompatImageView

대신에 android:src --> app:srcCompat

여기 예입니다

<android.support.v7.widget.AppCompatImageView
        android:layout_width="48dp"
        android:layout_height="48dp"
        android:id="@+id/button"
        app:srcCompat="@drawable/ic_more_vert_24dp"
        android:tint="@color/primary" />

@ Sayooj Valsan 언급 으로 gradle을 업데이트하는 것을 잊지 마십시오

// Gradle Plugin 2.0+  
 android {  
   defaultConfig {  
     vectorDrawables.useSupportLibrary = true  
   }  
 }  

 compile 'com.android.support:design:23.4.0'

주의 어떤 벡터를 사용하든 절대로 벡터에 색상을 참조하지 마십시오 android:fillColor="@color/primary".


이유를 결코 사용하지 @color위해 fillcolor?
HoseinIT

0

를 사용하지 않는 사람들을 ImageView위해 다음이 평범하게 작동했습니다 View(따라서 행동은 모든 종류의 관점에서 복제되어야 함)

<View
    android:background="@drawable/ic_reset"
    android:backgroundTint="@color/colorLightText" />
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.