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

Answers:


332

不要直接编辑矢量资产。如果在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种以上的设备上进行着色,您对棒棒糖之前的设备是否有任何建议
弄糊了2015年

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引用,否则仅适用于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引用不适用于棒棒糖之前的矢量(因此,矢量-> PNG转换)code.google.com/p/android/issues/detail?id=186431
PieterAelse,2016年

5
现在,@ color引用可用于所有Android版本的fillColor属性,但是它不支持颜色状态列表。
TheIT

看起来向量状态列表的方法是使用AnimatedStateListDrawable s
gMale

1
@TheIT我必须启用什么?似乎对我
没用-urSus

@PieterAelse我不确定,如果您想使用相同的资产但背景不同(该颜色类似于上一个答案),该怎么办。在您的解决方案中,您将拥有几个具有相同资源但填充颜色不同的实例
Anton Makov,

71

如其他答案中所述,不要直接编辑vector drawable,而是可以在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网站页脚说:“根据CC by-sa 3.0授权的用户贡献,需要提供
出处

进行了一些更改对我有用。谢谢您的帮助。
安德烈·路易斯·雷斯(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()已经过时
大卫·

如何将其用于TextView的drawable ***?
Hemant Kaushik

getColor(ResId)不推荐使用@David,但getColor(ResId, Theme)不建议使用。或者,ResourcesCompat.getColor(getResources(), R.color.primary, null);如果您不关心主题,则可以使用...,或者如果上下文/策略委托是一项活动,则可getTheme()以为最后一个参数执行。
Martin Marconcini

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

同样,mighr的颜色仍会保留在缓存中,因此为所有用户删除应用可能会有所帮助。


7

Android Studio现在支持向量棒棒糖前。没有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:tint只能在21个以上的设备上运行的其他答案,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
大鹏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

如果您希望支持旧版本的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'

注意 对于任何一个使用向量的人,永远不要像这样android:fillColor="@color/primary"给出十六进制值那样给向量引用颜色。


为什么从来没有使用@colorfillcolor
HoseinIT

0

对于不使用an的用户ImageView,以下内容在平原上对我有用View(因此,该行为应在任何视图上复制)

<View
    android:background="@drawable/ic_reset"
    android:backgroundTint="@color/colorLightText" />
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.