Ändern Sie die Füllfarbe des Vektor-Assets in Android Studio


175

Android Studio unterstützt jetzt Vektor-Assets ab 21 Jahren und generiert zum Zeitpunkt der Kompilierung PNGs für niedrigere Versionen. Ich habe ein Vektor-Asset (aus den Materialsymbolen), mit dem ich die Füllfarbe ändern möchte. Dies funktioniert bei 21+, aber die generierten PNGs ändern ihre Farbe nicht. Gibt es eine Möglichkeit, dies zu tun?

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

Antworten:


347

Bearbeiten Sie die Vektor-Assets nicht direkt. Wenn Sie einen Vektor verwenden, der in einem ImageButton gezeichnet werden kann, wählen Sie einfach Ihre Farbe in 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" />

25
Tönung funktioniert nur auf 21+ Geräten, haben Sie einen Vorschlag für Pre-Lollipop-Geräte
Mudit

12
android: tint funktioniert auf allen androidversionen seit APIv1. Was Sie meinen, ist drawableTint.
JJJJ-MM-TT

31
android:tintmuss nach seinandroid:src
EmmanuelMess

5
Was ist mit drawableLeftin Button?
Pratik Butani

8
@mudit versuchen Sie einen Vektor mit fillColor = "# colorvalue" zu verwenden, verwenden Sie keine @ color Referenz, da sie nur SDK 21+ für Vektoren (also nicht für die generierten
PNGs

100

Du kannst es schaffen.

ABER Sie können keine @ color-Referenzen für Farben (..lame) verwenden, da dies sonst nur für L + funktioniert

<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
Dies sollte die akzeptierte Antwort sein! @ Farbreferenzen funktionieren nicht in Vektoren vor Lollipop (also Vektor -> PNG-Konvertierung) code.google.com/p/android/issues/detail?id=186431
PieterAelse

6
@ color-Referenzen können jetzt für das fillColor-Attribut für alle Android-Versionen verwendet werden, es werden jedoch keine Farbstatuslisten unterstützt.
TheIT

Es sieht so aus, als ob die Art und Weise, Vektorstatuslisten zu
erstellen,

1
@TheIT was muss ich es aktivieren? Scheint nicht für mich zu funktionieren
urSus

@PieterAelse Ich bin mir nicht sicher, was ist, wenn Sie dasselbe Asset mit unterschiedlichen Hintergründen verwenden möchten (Farbtöne wie in der vorherigen Antwort). In Ihrer Lösung haben Sie mehrere Instanzen derselben Ressource, aber mit unterschiedlicher Füllfarbe
Anton Makov

71

Wie in anderen Antworten erwähnt, bearbeiten Sie den Vektor, der gezeichnet werden kann, nicht direkt, sondern Sie können Java-Code wie folgt einfärben:

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

Und der Einfachheit halber habe ich eine Hilfsklasse erstellt:

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

Gehen Sie zur Verwendung wie folgt vor:

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

Oder:

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

    actionBar.setHomeAsUpIndicator(drawable);

Hallo Filipe, danke für deine Antwort. Haben Sie eine Bibliothek, einen Code-Github, in dem wir die Lizenz sehen können? danke :)
Vincent D.

2
Nein, Vicent, überhaupt keine Lizenz. Die Lösung ist so einfach, dass ich denke, dass das hier verwendete Builder-Muster nicht notwendig ist. Aber jeder kann von dieser Lösung profitieren und ohne Lizenz verwenden.
Filipe Bezerra de Sousa

Gute Antwort! Funktioniert genau so, wie ich es brauche
Eoin

1
@ VincentD. In der Fußzeile der SO-Webseite steht "Benutzerbeiträge, die unter cc by-sa 3.0 mit Namensnennung lizenziert sind"
Shelll

Es hat bei mir mit einigen Änderungen funktioniert. Danke für deine Hilfe.
André Luiz Reis

40

Um die Farbe des Vektorbildes zu ändern, können Sie direkt android verwenden: 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" />

Programmgesteuert ändern

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

getColor () ist veraltet
David

Wie verwende ich es für TextViews Drawable ***?
Hemant Kaushik

getColor (ResId) ist @David veraltet, aber getColor(ResId, Theme)nicht. Oder Sie können verwenden, ResourcesCompat.getColor(getResources(), R.color.primary, null);wenn Sie sich nicht für das Thema interessieren ... oder wenn Ihr Kontext- / Richtliniendelegierter eine Aktivität ist, können Sie dies getTheme()für diesen letzten Parameter tun .
Martin Marconcini

16

Derzeit ist die Arbeitslösung android: fillColor = "# FFFFFF"

Für mich funktionierte nichts außer der harten Codierung im Vektor

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

Füllfarbe und Farbton könnten jedoch bald funktionieren. Weitere Informationen finden Sie in dieser Diskussion:

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

Auch die Farben mighr bleiben im Cache, so dass das Löschen der App für alle Benutzer hilfreich sein kann.


7

Android Studio unterstützt jetzt Vektoren vor dem Lutscher. Keine PNG-Konvertierung. Sie können Ihre Füllfarbe weiterhin ändern und es wird funktionieren.

Verwenden Sie in Ihrer ImageView

 app:srcCompat="@drawable/ic_more_vert_24dp"

In Ihrer Gradle-Datei

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

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

11
Die Frage ist "wie man die
Vektorfüllfarbe

6

Update: AppCompatUnterstützung

Andere Antworten, bei denen der Verdacht besteht, dass android:tintsie nur auf mehr als 21 Geräten funktionieren, bietet AppCompat ( Version 23.2.0 und höher ) jetzt eine abwärtskompatible Behandlung des Farbtonattributs.

Die Vorgehensweise wäre also, AppCompatImageViewund app:srcCompat(im AppCompat-Namespace) anstelle von android:src(Android-Namespace) zu verwenden.

Hier ist ein Beispiel (AndroidX: Dies ist 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" />

Und vergessen Sie nicht, die Unterstützung für Vektorzeichnungen in Gradle zu aktivieren:

vectorDrawables.useSupportLibrary = true 

Nur ein Update. Heutzutage AppCompatImageViewist der unterandroidx.appcompat.widget.AppCompatImageView
Roc Boronat

2

Fügen Sie diese Bibliothek dem Gradle hinzu, um den Farbvektor zu aktivieren, der in alten Android-Geräten gezeichnet werden kann.

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

und Gradle erneut synchronisieren. Ich denke, es wird das Problem lösen.


2

Wenn die Vektoren mit fillColor keine individuell festgelegten Farben anzeigen, werden sie möglicherweise auf einen Standard-Widget-Parameter festgelegt.

Versuchen Sie, app:itemIconTint="@color/lime"zu activity_main.xml hinzuzufügen , um einen Standardfarbtyp für die Widget-Symbole festzulegen.

<?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 @ developer.android


In Android Studio 3.6 ändern Sie in svg xml dieses Feld: android: fillColor = "# FFFFC400"
a_subscriber

1

Wenn Sie die alte Version vor Lolipop unterstützen möchten

Verwenden Sie mit einigen Änderungen denselben XML-Code

statt normal ImageView --> AppCompatImageView

anstatt android:src --> app:srcCompat

Hier ist ein Beispiel

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

Vergessen Sie nicht, Ihren Gradle zu aktualisieren, wie @ Sayooj Valsan erwähnt

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

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

Hinweis Wenn Sie einen Vektor verwenden, geben Sie Ihrem Vektor niemals einen Bezug zu einer Farbe wie dieser, und android:fillColor="@color/primary"geben Sie dessen Hex-Wert an.


warum nie @colorfür verwenden fillcolor?
HoseinIT

0

Für diejenigen, die kein verwenden ImageView, hat das Folgende für mich in einer Ebene funktioniert View(und daher sollte sich das Verhalten in jeder Art von Ansicht wiederholen).

<View
    android:background="@drawable/ic_reset"
    android:backgroundTint="@color/colorLightText" />

0

Gehen Sie zu MainActivity.java und unter diesem Code
-> NavigationView navigationView = findViewById(R.id.nav_view);
Fügen Sie eine einzelne Codezeile hinzu -> navigationView.setItemIconTintList(null);
dh die letzte Zeile meines Codes

Ich hoffe, das könnte Ihr Problem lösen.

public class MainActivity extends AppCompatActivity {

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

        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        navigationView.setItemIconTintList(null);
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.