在 Android Studio 中更改矢量资源的填充颜色

Change fill color on vector asset in Android Studio

Android Studio 现在支持 21+ 上的矢量资源,并将在编译时为较低版本生成 png。我有一个矢量资产(来自 Material 图标),我想更改填充颜色。这适用于 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"/>

不要直接编辑矢量资源。如果您在 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" />

你可以的。

但是你不能对颜色使用@color 引用(..lame),否则它将仅适用于 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"/>

目前的工作解决方案是 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

此外,颜色可能会保留在缓存中,因此为所有用户删除应用程序可能会有所帮助。

如其他答案所述,不要直接编辑矢量可绘制对象,而是可以在 java 代码中着色,如下所示:

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

为了简单起见,我创建了一个助手 class:

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

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'

要更改矢量图像颜色,您可以直接使用 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));

如果你希望支持老版本的 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" />

别忘了将您的 gradle 更新为@ Sayooj Valsan 提及

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

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

注意任何使用矢量的人都永远不要像这样给你的矢量参考颜色android:fillColor="@color/primary"给出它的十六进制值。

将此库添加到 Gradle 以在旧 android 设备中启用颜色矢量可绘制。

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

并重新同步 gradle。我认为它会解决问题。

更新:AppCompat支持

其他答案怀疑 android:tint 是否仅适用于 21+ 设备,AppCompat(v23.2.0 及更高版本) 现在提供色调属性的向后兼容处理。

因此,操作过程是使用 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 

如果矢量未显示使用 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

对于那些不使用 ImageView 的人,以下内容对我来说很简单 View(因此该行为应该在任何类型的视图上复制)

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

去找你MainActivity.java 在此代码下方
-> NavigationView navigationView = findViewById(R.id.nav_view);
添加单行代码 -> navigationView.setItemIconTintList(null);
即我代码的最后一行

希望这可以解决您的问题。

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

如果你想改变项目矢量图标的颜色,你可以使用这个:

android:iconTint="@color/color"

如果矢量资源在 CardView 中,请尝试 card_view:tint="@color/secondary" 在 ImageView 中。 注意:将 @color/secondary 替换为您想要的颜色。

对于我的 ImageButton,我使用 app:tint="@color/green" 而不是 android:tint

使用

android:drawableTint="@color/primary"

在activity_main.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="24"
    android:viewportHeight="24"
    android:tint="//Your Color Code//">
  <path
      android:fillColor="@android:color/white"
      android:pathData="M11,9.16V2c-5,0.5 -9,4.79 -9,10s4,9.5 9"/>
</vector>

这是 Filipe

的 Drawable Helper 的 Kotlin 版本
class DrawableHelper(var mContext: Context) {
    @ColorRes
    private var mColor = 0
    private lateinit var mDrawable: Drawable
    private lateinit var mWrappedDrawable: Drawable
    fun withDrawable(@DrawableRes drawableRes: Int): DrawableHelper {
        mDrawable = getDrawable(mContext, drawableRes)!!
        return this
    }

    fun withDrawable(drawable: Drawable): DrawableHelper {
        mDrawable = drawable
        return this
    }

    @SuppressLint("ResourceType")
    fun withColor(@ColorRes colorRes: Int): DrawableHelper {
        mColor = ContextCompat.getColor(mContext, colorRes)
        return this
    }

    @SuppressLint("ResourceAsColor")
    fun tint(): DrawableHelper {
        mWrappedDrawable = DrawableCompat.wrap(mWrappedDrawable)
        DrawableCompat.setTint(mWrappedDrawable, mColor)
        DrawableCompat.setTintMode(mWrappedDrawable, PorterDuff.Mode.SRC_IN)
        return this
    }

    fun applyToBackground(view: View) {
        view.background = mWrappedDrawable
    }

    fun applyTo(imageView: ImageView) {
        imageView.setImageDrawable(mWrappedDrawable)
    }

    fun applyTo(menuItem: MenuItem) {
        menuItem.icon = mWrappedDrawable
    }

    fun get(): Drawable {
        return mWrappedDrawable
    }

    companion object {
        fun withContext(context: Context): DrawableHelper {
            return DrawableHelper(context)
        }
    }
}