从 Android L 开始,Material Theme 能够借助某些属性主题化 APP(图标及其他)
|
|
这种方式能够节省很多时间。只需修改一次就能改变整个 APP 的颜色,或调整单个 drawable 的颜色,而不需要找设计师拿新的资源。
我们可以通过查看 ImageView 的 android:tint
属性来了解这种方式是如何执行的。你可以在 xml 中设置一个 tint
color,噢!资源的颜色已经不一样了!
对于 ImageView 的 tint 属性,应当注意两点:
ImageView 的 tint 会混合 tint color 以及原来的资源。你希望 tint color 为主,而不是将 tint 叠加于现有颜色的上方。例如,如果原来资源是黑色的(#FF000000),而你希望它变成 #77FFFFFF(半透白色阴影),最终你得到的是白色阴影叠加在黑色背景之上。
-
android:tint
仅限于 ImageView,但你想全部有 Drawable 的 View 也能实现这种效果。
通过阅读 ImageView 中 tint 相关的实现,可以知道通过 ColorFilter 即能轻易地解决上述两个问题。更详细地,ImageView 使用了 Porter/Duff 将相应颜色应用到图片的上层来合成而达到 tint 的效果。
为了解决第一个问题,我们只需要使用不同的 Porter/Duff 模式。ImageView 使用的是 PorterDuff.Mode.SRC_ATOP
,该模式将 tint color 叠加于图片的上层中(但仍然将原图绘制在下方)。对于主题化,我们实际需要的是 PorterDuff.Mode.SRC_IN
,该模式只会绘制 tint color。
第二个问题也能轻易地避免,因为所有 Drawable 对象都有 setColorFilter()
方法。
利用该方法将相应主题颜色应用到 View 的背景中的简单实例:
|
|
你也可以封装一个可复用的用于创建不同颜色 Drawable 的方法:
|
|
(附注:使用 @DrawableRes
、@ColorRes
注解可以帮助我们避免调用方法时传入错误的参数。)
虽然这种方式不如 Android L 那么方便地主题化,但该方法可向下兼容,所以你也可以考虑使用。
附录
Added July 24, 2015
提醒一句:使用 ColorFilter
时会影响到 Drawable
的状态共享。
作为优化,Drawable 会在应用内共享。例如,在不同的 Toolbar
中使用相同的 Action Bar 图标实际上只会产生一个 Drawable。同样地,如果你使用 ColorFilter
,你可能会发现所有的 Drawable 都会发生变化即使你希望只改变其中一个。
这篇文章更深入地介绍了这种优化策略。如果你正在使用 ColorFilter
并且不希望改变所有的 Drawable,确保先调用
Drawable.mutate()
再执行其他操作。