以编程方式为支持向量着色
Programmatically tint a Support Vector
AndroidStudio 2.1版本,gradle2.1.0版本,如有错误请指正:)
我对支持库 23.3.0 中的支持向量感到困惑。具体来说,我想做的是以编程方式为图像按钮着色,其 src 被定义为可绘制的矢量。据我所知,这在棒棒糖之前是不可能的。
我已阅读几篇有关更改的相关 post:
23.2.0 announcement and changes:
As of Android Support Library 23.3.0, support vector drawables can only be loaded via app:srcCompat or setImageResource().
以上是否意味着矢量 xml 只能通过 srcCompat 或 setImageResource() 在 Lollipop 之前使用,因此 不能动态着色?
这是我的基本图像按钮:
<ImageButton
android:id="@+id/nav_header_exit_community_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:background="@null"/>
仅适用于 Lollipop 及更高版本:
Drawable bg = ContextCompat.getDrawable(a, R.drawable.ic_exit_to_app_24dp);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageDrawable(bg);
尝试这个预棒棒糖抛出:
android.content.res.Resources$NotFoundException: File res/drawable/ic_exit_to_app_24dp.xml from drawable resource ID #0x7f0200bf
也仅适用于 Lollipop 及更高版本
Drawable bg = ContextCompat.getDrawable(a, R.drawable.ic_exit_to_app_24dp);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageResource(R.drawable.ic_exit_to_app_24dp);
这会在 pre-Lollipop 上引发相同的错误。
但是,如果我按照 的指示删除 vectorDrawables.useSupportLibrary = true
,目的是让构建工具为 Lollipop 之前的设备自动生成 png,png 不会在棒棒糖前染色,所以我回到原点。
我也尝试通过 srcCompat
指定向量并以编程方式检索它,但我认为我无法实现这一点,即使它适用于 post-Lollipop 如果向量是使用 src
指定的。
因此 23.3.0 的情况似乎是:
Post-棒棒糖:src
和srcCompat
接受向量,只有src
可以
从视图中检索为可绘制对象,用于以编程方式进行着色。
使用 getDrawable 可以在代码中引用向量,它们
可以染色。
Pre-Lollipop: srcCompat 只能接受向量,无法检索
以编程方式从视图进行着色。 setImageResource
可以
接受向量,但前提是 vectorDrawables.useSupportLibrary = false
,并且着色不起作用。同样在代码中引用向量不是
可能,除非 vectorDrawables.useSupportLibrary = false
和着色
不起作用。
使用 png 处理所有版本:
Drawable bg = ContextCompat.getDrawable(a, R.drawable.ic_nav_exit_community);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageDrawable(bg);
附录:
此技术也适用于 post-Lollipop,但与其他 Lollipop 之前的技术一样,我得到了可绘制对象,但没有着色:
Drawable bg = VectorDrawableCompat.create(a.getResources(), R.drawable.ic_exit_to_app_24dp, null);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageDrawable(bg);
解决方案种类:
感谢 的回答,到目前为止,我能想出的唯一万无一失的方法是在支持向量上设置一个滤色器——这意味着 DrawableCompat.setTint()
函数是如果有问题的可绘制对象是支持向量,那么对我来说似乎不起作用。我不确定这是一个合法的错误、预期的行为还是我只是做错了什么!
这是我目前要使用的解决方案:
Drawable bg;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
bg = VectorDrawableCompat.create(a.getResources(), R.drawable.ic_exit_to_app_24dp, null);
exitButton.setColorFilter(headerTitleColor, PorterDuff.Mode.MULTIPLY);
}
else {
bg = ContextCompat.getDrawable(a, R.drawable.ic_exit_to_app_24dp);
DrawableCompat.setTint(bg, headerTitleColor);
}
exitButton.setImageDrawable(bg);
可以使用ImageView的setColorFilter方法:
imageView.setColorFilter(headerTitleColor, android.graphics.PorterDuff.Mode.MULTIPLY);
首先你应该使用 VectorDrawableCompat#create
,一旦你有你的 Drawable
你必须调用 DrawableCompat#wrap
:
Potentially wrap drawable so that it may be used for tinting across
the different API levels, via the tinting methods in this class.
因此您的代码将如下所示:
ImageView iv = ....
Drawable d = VectorDrawableCompat.create(getResources(), R.drawable.ic_exit_to_app_24dp, null);
d = DrawableCompat.wrap(d);
DrawableCompat.setTint(d, headerTitleColor);
iv.setImageDrawable(d);
Kotlin 的另一个便捷解决方案:
fun Context.drawableWithColor(@DrawableRes drawableRes: Int, @ColorInt color: Int): Drawable? {
val pic = ContextCompat.getDrawable(this, drawableRes)
pic?.setColorFilter(color, PorterDuff.Mode.SRC_IN)
return pic
}
使用很简单:
val drawable = context.drawableWithColor(R.drawable.your_awesome_drawable, Color.BLUE)
AndroidStudio 2.1版本,gradle2.1.0版本,如有错误请指正:)
我对支持库 23.3.0 中的支持向量感到困惑。具体来说,我想做的是以编程方式为图像按钮着色,其 src 被定义为可绘制的矢量。据我所知,这在棒棒糖之前是不可能的。
我已阅读几篇有关更改的相关 post: 23.2.0 announcement and changes:
As of Android Support Library 23.3.0, support vector drawables can only be loaded via app:srcCompat or setImageResource().
以上是否意味着矢量 xml 只能通过 srcCompat 或 setImageResource() 在 Lollipop 之前使用,因此 不能动态着色?
这是我的基本图像按钮:
<ImageButton
android:id="@+id/nav_header_exit_community_button"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_alignParentTop="true"
android:layout_alignParentRight="true"
android:background="@null"/>
仅适用于 Lollipop 及更高版本:
Drawable bg = ContextCompat.getDrawable(a, R.drawable.ic_exit_to_app_24dp);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageDrawable(bg);
尝试这个预棒棒糖抛出:
android.content.res.Resources$NotFoundException: File res/drawable/ic_exit_to_app_24dp.xml from drawable resource ID #0x7f0200bf
也仅适用于 Lollipop 及更高版本
Drawable bg = ContextCompat.getDrawable(a, R.drawable.ic_exit_to_app_24dp);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageResource(R.drawable.ic_exit_to_app_24dp);
这会在 pre-Lollipop 上引发相同的错误。
但是,如果我按照 vectorDrawables.useSupportLibrary = true
,目的是让构建工具为 Lollipop 之前的设备自动生成 png,png 不会在棒棒糖前染色,所以我回到原点。
我也尝试通过 srcCompat
指定向量并以编程方式检索它,但我认为我无法实现这一点,即使它适用于 post-Lollipop 如果向量是使用 src
指定的。
因此 23.3.0 的情况似乎是:
Post-棒棒糖:
src
和srcCompat
接受向量,只有src
可以 从视图中检索为可绘制对象,用于以编程方式进行着色。 使用 getDrawable 可以在代码中引用向量,它们 可以染色。Pre-Lollipop: srcCompat 只能接受向量,无法检索 以编程方式从视图进行着色。
setImageResource
可以 接受向量,但前提是vectorDrawables.useSupportLibrary = false
,并且着色不起作用。同样在代码中引用向量不是 可能,除非vectorDrawables.useSupportLibrary = false
和着色 不起作用。
使用 png 处理所有版本:
Drawable bg = ContextCompat.getDrawable(a, R.drawable.ic_nav_exit_community);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageDrawable(bg);
附录:
此技术也适用于 post-Lollipop,但与其他 Lollipop 之前的技术一样,我得到了可绘制对象,但没有着色:
Drawable bg = VectorDrawableCompat.create(a.getResources(), R.drawable.ic_exit_to_app_24dp, null);
DrawableCompat.setTint(bg, headerTitleColor);
exitButton.setImageDrawable(bg);
解决方案种类:
感谢 DrawableCompat.setTint()
函数是如果有问题的可绘制对象是支持向量,那么对我来说似乎不起作用。我不确定这是一个合法的错误、预期的行为还是我只是做错了什么!
这是我目前要使用的解决方案:
Drawable bg;
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
bg = VectorDrawableCompat.create(a.getResources(), R.drawable.ic_exit_to_app_24dp, null);
exitButton.setColorFilter(headerTitleColor, PorterDuff.Mode.MULTIPLY);
}
else {
bg = ContextCompat.getDrawable(a, R.drawable.ic_exit_to_app_24dp);
DrawableCompat.setTint(bg, headerTitleColor);
}
exitButton.setImageDrawable(bg);
可以使用ImageView的setColorFilter方法:
imageView.setColorFilter(headerTitleColor, android.graphics.PorterDuff.Mode.MULTIPLY);
首先你应该使用 VectorDrawableCompat#create
,一旦你有你的 Drawable
你必须调用 DrawableCompat#wrap
:
Potentially wrap drawable so that it may be used for tinting across the different API levels, via the tinting methods in this class.
因此您的代码将如下所示:
ImageView iv = ....
Drawable d = VectorDrawableCompat.create(getResources(), R.drawable.ic_exit_to_app_24dp, null);
d = DrawableCompat.wrap(d);
DrawableCompat.setTint(d, headerTitleColor);
iv.setImageDrawable(d);
Kotlin 的另一个便捷解决方案:
fun Context.drawableWithColor(@DrawableRes drawableRes: Int, @ColorInt color: Int): Drawable? {
val pic = ContextCompat.getDrawable(this, drawableRes)
pic?.setColorFilter(color, PorterDuff.Mode.SRC_IN)
return pic
}
使用很简单:
val drawable = context.drawableWithColor(R.drawable.your_awesome_drawable, Color.BLUE)