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以上のデバイスでのみ機能しますが、ロリポップ前のデバイスについて何か提案はありますか
mudit

12
android:tintは、APIv1以降のすべてのAndroidバージョンで機能します。つまり、drawableTintです。
YYYY-MM-DD

31
android:tint後にする必要がありますandroid:src
EmmanuelMess

5
何についてdrawableLeftButton
Pratik Butani 2016年

8
@muditは、fillColor = "#colorvalue"でベクターを使用してみます。@ color参照は使用しないでください。これは、SDK 21+がベクターに対してのみ機能するためです(生成されたPNGでは機能しない)
PieterAelse

95

できます。

ただし、色(..lame)に@color参照を使用することはできません。それ以外の場合は、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"/>


11
これは受け入れられる答えになるはずです!@color参照はロリポップより前のベクター(つまり
PieterAelse

5
@color参照をすべてのAndroidバージョンのfillColor属性に使用できるようになりましたが、カラー状態リストはサポートしていません。
TheIT

ベクトル状態リストを行う方法はAnimatedStateListDrawable s を使用するように見えます
gMale

1
@TheIT有効にするには何が必要ですか?うまく機能しないようです
urSus

@PieterAelse確かではありませんが、同じアセットを異なる背景で使用したい場合はどうすればよいでしょうか(前の回答のような色合い)。あなたのソリューションでは、同じリソースのインスタンスがいくつかありますが、塗りつぶしの色が異なります
アントンマコフ2018

71

他の回答で述べたように、ベクトルドローアブルを直接編集しないでください。代わりに、次のようにJavaコードで色付けできます。

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

こんにちはフィリッペ、あなたの答えをありがとう。ライセンスを確認できるライブラリ、省略コードgithubはありますか?おかげで:)
ヴィンセントD。16年

2
いいえ、Vicent、ライセンスはまったくありません。ここで使用されているBuilderパターンは必要ないので、非常に単純なソリューションです。しかし、誰でもこのソリューションの恩恵を受け、ライセンスなしで使用できます。
Filipe Bezerra de Sousa

正解です。私の必要とまったく同じように機能します
Eoin

1
@VincentD。SO Webページのフッターには、「帰属表示が必要なcc by-sa 3.0でライセンスされたユーザー投稿」と記載されています
shelll

それは私にいくつかの変更を加えて機能しました。ご協力ありがとうございました。
アンドレ・ルイス・レイス

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()は非推奨
デビッド

TextViewのドローアブルに使用する方法***?
Hemant Kaushik

getColor(ResId)は非推奨の@Davidですが、非推奨でgetColor(ResId, Theme)はありません。またはResourcesCompat.getColor(getResources(), R.color.primary, null);、テーマを気にしない場合、またはコンテキスト/ポリシーデリゲートがアクティビティである場合はgetTheme()、最後のパラメーターに対して実行できます。
マルタンマルコンチーニ

15

現在のところ、解決策は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

また、色の移行はキャッシュに残るため、すべてのユーザーのアプリを削除すると役立つ場合があります。


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
質問は「ベクトル資産を使用する方法」、「どのようにベクトル塗りつぶしの色を変更する」ではありません
レオDroidcoder

5

更新: AppCompatサポート

android:tint21以上のデバイスのみで動作するかどうかを疑うその他の回答、AppCompat(v23.2.0以上は、tint属性の下位互換性のある処理を提供する。

したがって、アクションのコースはAppCompatImageViewapp:srcCompat(AppCompat名前空間で)の代わりにandroid:src(Android名前(ます。

次に例を示します(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 @ developers.android


Android Studio 3.6では、svg xmlでこのフィールドを変更します:android:fillColor = "#FFFFC400"
a_subscriber

1

古いバージョンのpre lolipopをサポートする場合

いくつかの変更を加えて同じ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'

注意 いずれか1つの使用ベクトルに対して、このようなカラーへのベクトル参照をandroid:fillColor="@color/primary"16進値で与えてはなりません。


なぜ使用@colorfillcolorないのですか?
HoseinIT 2017

0

を使用していない人のためImageViewに、以下は私にとってはプレーンで機能しましたView(したがって、動作はあらゆる種類のビューで再現されるはずです)

<View
    android:background="@drawable/ic_reset"
    android:backgroundTint="@color/colorLightText" />
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.