以下从三个方面进行介绍Drawables:
* Drawable tinting (着色)
* Prominent color extraction(颜色提取)
* Vector drawables(矢量图片)
Tint Drawable Resources
以下部分介绍转自:http://segmentfault.com/a/1190000003038675?utm_source=tuicool&utm_medium=referral
什么是Tint
当我开始接触Tint这个词的时候,其实是蛮不理解它的意思的,以及并不清楚Google发明它的目的,它一般搭配Background配合使用,但是现在已经有了Background,为什么还需要Tint呢?
Tint 翻译为着色。
着色,着什么色呢?和背景有关,当然是着背景的色。当我开发客户端,使用了appcompat-v7包的时候,为了实现Material
Design的效果,我们会去设置主题里的几个颜色,重要的比如primaryColor,colorControlNormal,colorControlActived
等等,而我们使用的一些组件,比如EditText就会自动变成我们想要的背景颜色,在背景图只有一张的情况下,这样的做法极大的减少了我们apk包的大小。
实现的方式就是用一个颜色为我们的背景图片设置tint(着色)。 例子:看看即将发布的SegmentFault for Android
2.7中,发布问题功能,这个EditText的颜色和我们的主要颜色相同。它利用了TintManager这个类,为自己的背景进行着色(绿色)。 那么这个原始图是什么样子呢?我们从appcompat-v7包中找到了这个图,是一个.9图,样子如下:其实它只是一个黑色的条,通过绿色的着色,变成了一个绿色的条。 就是这样的设计方式,使得我们在Material
Design中省了多少资源文件呀! 好了,既然理解了tint的含义,我们赶紧看下这一切是如何实现的吧。
其实底层特别简单,了解过渲染的同学应该知道PorterDuffColorFilter这个东西,我们使用SRC_IN的方式,对这个Drawable进行颜色方面的渲染,就是在这个Drawable中有像素点的地方,再用我们的过滤器着色一次。
实际上如果要我们自己实现,只用获取View的backgroundDrawable之后,设置下colorFilter即可。
看下最核心的代码就这么几行
if (filter == null) {
// Cache miss, so create a color filter and add it to the cache
filter = new PorterDuffColorFilter(color, mode);
}d.setColorFilter(filter); d.setColorFilter(filter); 由于API Level 21以前不支持background
tint在xml中设置(android:tint和android:tintMod),于是提供了ViewCompat.setBackgroundTintList方法和ViewCompat.setBackgroundTintMode用来手动更改需要着色的颜色,但要求相关的View继承TintableBackgroundView接口。
TintMode的类型有以下16种:
1.PorterDuff.Mode.CLEAR 所绘制不会提交到画布上。
2.PorterDuff.Mode.SRC 显示上层绘制图片
3.PorterDuff.Mode.DST 显示下层绘制图片
4.PorterDuff.Mode.SRC_OVER 正常绘制显示,上下层绘制叠盖。
5.PorterDuff.Mode.DST_OVER 上下层都显示。下层居上显示。
6.PorterDuff.Mode.SRC_IN 取两层绘制交集。显示上层。
7.PorterDuff.Mode.DST_IN 取两层绘制交集。显示下层。
8.PorterDuff.Mode.SRC_OUT 取上层绘制非交集部分。
9.PorterDuff.Mode.DST_OUT 取下层绘制非交集部分。
10.PorterDuff.Mode.SRC_ATOP 取下层非交集部分与上层交集部分
11.PorterDuff.Mode.DST_ATOP 取上层非交集部分与下层交集部分
12.PorterDuff.Mode.XOR 异或:去除两图层交集部分
13.PorterDuff.Mode.DARKEN 取两图层全部区域,交集部分颜色加深
14.PorterDuff.Mode.LIGHTEN 取两图层全部,点亮交集部分颜色
15.PorterDuff.Mode.MULTIPLY 取两图层交集部分叠加后颜色
16.PorterDuff.Mode.SCREEN 取两图层全部区域,交集部分变为透明色
从图像中提取颜色(Palette)
Android Support Library r21 r21 及更高版本提供了Palette 类,以便我们从图像提取颜色,主要的颜色类型有以下六种:
* vibrant(鲜艳色)
* dark vibrant(鲜艳色中的暗色)
* light vibrant(鲜艳色中的亮色)
* muted(柔和色)
* dark muted(柔和色中的暗色)
* light muted(柔和色中的亮色)
###使用:
1.首先需要添加依赖:
dependencies {
...
compile 'com.android.support:palette-v7:21.0.0'
}
2.创建示例
- 同步方法(尽量避免在主线程中使用):
Palette p = Palette.from(bitmap).generate();
- 异步方法(在异步线程中执行完之后通过监听器回调)
// Asynchronous
Palette.from(bitmap).generate(new PaletteAsyncListener() {
public void onGenerated(Palette p) {
// Use generated instance
}
});
3.获取颜色
- 通过提供的getter函数直接获取以上提及的六种类型颜色:
Palette palette = Palette.from(bitmap).generate();
int vibrant = palette.getVibrantColor(0x000000);
int vibrantLight = palette.getLightVibrantColor(0x000000);
//提取失败则返回指定的颜色:0x000000
......
- 通过Swatch对象提取(Swatch里面含有很多关于对应颜色的有用信息)
Palette palette = Palette.from(bitmap).generate();
Palette.Swatch swatch = palette.getVibrantSwatch();
//rgb颜色值
int rgbColor = swatch.getRgb();
//hsl颜色向量
float[] hslValues = swatch.getHsl();
//该颜色在图像中所占的像素数
int pixelCount = swatch.getPopulation();
//对应的标题字体颜色
int titleTextColor = swatch.getTitleTextColor();
//对应的正文字体颜色
int bodyTextColor = swatch.getBodyTextColor();
4:来自网上的一张demo示例图:
矢量图片(Vector Drawables)
见下一章