Ubah warna isian pada aset vektor di Android Studio

169

Android Studio sekarang mendukung aset vektor pada 21+ dan akan menghasilkan png untuk versi yang lebih rendah pada waktu kompilasi. Saya memiliki aset vektor (dari Material Ikon) yang ingin saya ubah warna isiannya. Ini berfungsi di 21+, tetapi png yang dihasilkan tidak berubah warna. Apakah ada cara untuk melakukan ini?

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

Patrick
sumber

Jawaban:

333

Jangan mengedit aset vektor secara langsung. Jika Anda menggunakan gambar vektor di ImageButton, pilih saja warna Anda 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" />
YYYY-MM-DD
sumber
24
pewarnaan hanya bekerja di 21+ perangkat, apakah Anda punya saran untuk perangkat pra-lolipop
mudit
12
android: tint berfungsi pada semua versi android sejak APIv1. Apa yang Anda maksud drawableTint.
YYYY-MM-DD
31
android:tintharus setelahandroid:src
EmmanuelMess
5
Bagaimana drawableLeftdi Button?
Pratik Butani
8
@mudit coba gunakan vektor dengan fillColor = "# colorvalue", jangan gunakan referensi @ color karena mereka hanya bekerja SDK 21+ untuk vektor (jadi tidak untuk PNG yang dihasilkan)
PieterAelse
95

Kamu bisa melakukannya.

TETAPI Anda tidak dapat menggunakan referensi @color untuk warna (..lame), jika tidak, ia hanya akan berfungsi untuk L +

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

urus
sumber
11
Ini harus menjadi jawaban yang diterima! Referensi @color tidak berfungsi dalam vektor pra-Lollipop (jadi vektor -> konversi PNG) code.google.com/p/android/issues/detail?id=186431
PieterAelse
5
Referensi @color sekarang dapat digunakan untuk atribut fillColor untuk semua versi Android, namun itu tidak mendukung daftar status warna.
TheIT
Sepertinya cara untuk melakukan daftar keadaan vektor adalah dengan AnimatedStateListDrawable s
gMale
1
@TheIT apa yang harus saya aktifkan? Tampaknya tidak berfungsi untuk saya
urSus
@PieterAelse Saya tidak yakin, bagaimana jika Anda ingin menggunakan aset yang sama tetapi dengan latar belakang yang berbeda (warna seperti pada jawaban sebelumnya). Dalam solusi Anda, Anda akan memiliki beberapa contoh sumber daya yang sama tetapi dengan warna isi yang berbeda
Anton Makov
71

Seperti yang dikatakan dalam jawaban lain, jangan mengedit vektor yang dapat digambar secara langsung, alih-alih Anda dapat mewarnai kode java, seperti itu:

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

Dan demi kesederhanaan, saya telah menciptakan kelas pembantu:

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

Untuk menggunakan lakukan saja hal berikut:

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

Atau:

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

    actionBar.setHomeAsUpIndicator(drawable);
Filipe Bezerra de Sousa
sumber
Hai Filipe, terima kasih atas jawaban Anda. Apakah Anda memiliki pustaka, potongan kode github di mana kita dapat melihat lisensi? terima kasih :)
Vincent D.
2
Tidak Vicent, tidak ada lisensi sama sekali. Solusinya sangat sederhana sehingga saya kira pola Builder yang digunakan di sini tidak perlu. Tetapi siapa pun dapat memanfaatkan solusi ini dan menggunakannya tanpa lisensi.
Filipe Bezerra de Sousa
Jawaban bagus! Bekerja persis seperti yang saya butuhkan
Eoin
1
@VincentD. Footer halaman web SO mengatakan "kontribusi pengguna dilisensikan di bawah cc by-sa 3.0 dengan atribusi yang diperlukan"
shelll
Ini berhasil bagi saya dengan beberapa perubahan. Terima kasih untuk bantuannya.
André Luiz Reis
36

Untuk mengubah warna gambar vektor, Anda dapat langsung menggunakan 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" />

Untuk mengubah warna secara terprogram

ImageView ivVectorImage = (ImageView) findViewById(R.id.ivVectorImage);
ivVectorImage.setColorFilter(getResources().getColor(R.color.colorPrimary));
Rana Ranvijay Singh
sumber
getColor () sudah tidak digunakan lagi
David
Bagaimana cara menggunakannya untuk *** TextView yang dapat ditarik?
Hemant Kaushik
getColor (ResId) sudah usang @ David, tetapi getColor(ResId, Theme)tidak. Atau Anda dapat menggunakan ResourcesCompat.getColor(getResources(), R.color.primary, null);jika Anda tidak peduli dengan tema ... atau jika delegasi konteks / kebijakan Anda adalah suatu kegiatan, Anda dapat melakukannya getTheme()untuk parameter terakhir itu.
Martin Marconcini
15

Saat ini soloution yang berfungsi adalah android: fillColor = "# FFFFFF"

Tidak ada yang berhasil untuk saya kecuali pengodean keras dalam 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"/>

Namun, fillcolor dan tint mungkin segera berfungsi. Silakan lihat diskusi ini untuk informasi lebih lanjut:

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

Juga warna mighr menempel di cache sehingga menghapus aplikasi untuk semua pengguna dapat membantu.

sivi
sumber
7

Studio Android sekarang mendukung vektor pre-lollipop. Tidak ada konversi PNG. Anda masih dapat mengubah warna isian Anda dan itu akan berhasil.

Di ImageView Anda, gunakan

 app:srcCompat="@drawable/ic_more_vert_24dp"

Di file gradle Anda,

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

 compile 'com.android.support:design:23.4.0'
Sayooj Valsan
sumber
10
Pertanyaannya adalah "bagaimana cara mengubah warna isian vektor", bukan "bagaimana menggunakan aset vektor"
Leo Droidcoder
5

Perbarui: AppCompatdukungan

Jawaban lain yang mencurigakan jika hanya android:tintakan bekerja pada 21 perangkat saja, AppCompat ( v23.2.0 dan yang lebih tinggi ) sekarang menyediakan penanganan atribut warna yang kompatibel dengan terbelakang.

Jadi, tindakannya adalah menggunakan AppCompatImageViewdan app:srcCompat(dalam namespace AppCompat) alih-alih android:src(Android namespace).

Berikut ini sebuah contoh (AndroidX: Ini adalah 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" />

Dan jangan lupa untuk mengaktifkan dukungan gambar vektor di gradle:

vectorDrawables.useSupportLibrary = true 
Manish Kumar Sharma
sumber
Hanya pembaruan. Saat AppCompatImageViewini di bawahandroidx.appcompat.widget.AppCompatImageView
Roc Boronat
2

Tambahkan perpustakaan ini ke Gradle untuk mengaktifkan vektor warna yang dapat digambar di Perangkat Android lama.

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

dan sinkronisasi ulang gradle. Saya pikir itu akan menyelesaikan masalah.

Siddhartha Maji
sumber
2

Jika vektor tidak menunjukkan pengaturan warna secara individual menggunakan fillColor maka mereka dapat diatur ke parameter widget default.

Coba tambahkan app:itemIconTint="@color/lime"ke activity_main.xml untuk menetapkan jenis warna default untuk ikon widget.

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

lubi
sumber
Di Android studio 3.6, ubah svg xml bidang ini: android: fillColor = "# FFFFC400"
a_subscriber
1

jika Anda ingin mendukung pre lolipop versi lama

gunakan kode xml yang sama dengan beberapa perubahan

bukannya normal ImageView --> AppCompatImageView

dari pada android:src --> app:srcCompat

di sini adalah contoh

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

jangan lupa perbarui grad Anda sebagai @ Sayooj Valsan sebutkan

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

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

Perhatikan Untuk siapa pun yang menggunakan vektor, jangan pernah memberikan referensi vektor Anda ke warna seperti ini android:fillColor="@color/primary"memberikan nilai hex.

Mina Fawzy
sumber
mengapa tidak pernah menggunakan @coloruntuk fillcolor?
HoseinIT
0

Bagi mereka yang tidak menggunakan ImageView, berikut ini berfungsi untuk saya di dataran View(dan karenanya perilaku harus meniru pada segala jenis tampilan)

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