w4lle's Notes

人生如逆旅,我亦是行人。

w4lle's avatar w4lle

Android Color位移操作

背景

之前项目中有个改变颜色的透明度的需求,大概的意思是滑动动态的改变透明度,但是不可以改变View的透明度,必须改变颜色值得透明度,功能虽然是实现了,但是代码太ugly,所以重新写了一下,复习了下Color的相关知识和位移的操作。

Color简介

我们知道Color的每个颜色通道(channel)的组成由8位(bit)为一个单位,即1个字节(byte),10进制的取值范围0~255,我们一般用16进制表示,以0x开头,取值范围在0x00~0xFF。

Android中颜色一般有两种表示方法

  1. rgb:每8bit表示rgb中的一个颜色通道。
  2. argb:相比上第一种表示方法多出8bit用于表示alpha通道
    所以Color的表示是这样的:0xffff00ff。

题外话,讲到这里又想到了Bitmap.Config,熟悉bitmap操作的同学应该对此不陌生,创建bitmap时的配置参数。包括:

  1. ALPHA_8:只有一个alpha颜色通道,图形参数由一个字节来表示,是一种8位的位图。
  2. ARGB_4444:图形颜色通道argb分别占用4、4、4、4bit,也就是每个像素暂用2byte的内存空间,是一种16bit的视图。
  3. ARGB_8888:同上,每个像素占用4byte的内存空间。是一种32bit的视图。
  4. RGB_565:没有alpha颜色通道,占用16bit
    所以在创建视图的时候加入使用ARGB_8888,800480的视图,那么大概占用的空间就可以算出来了:800400*4byte/1024=1250kb。

实现

之前说了,我们的需求是提取出alpha值然后改变它的值,再生成一个新的color,为什么说之前的那种实现方式很丑呢,看代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (vertical >= 0) {
float toolBarAlpha = vertical * 1.0f / ivTop.getHeight();
if (toolBarAlpha > 1) {
toolBarAlpha = 1;
} else if (toolBarAlpha < 0) {
toolBarAlpha = 0;
}
int tmp = (int) (0xff * toolBarAlpha);
String alpha = Integer.toHexString(tmp);
if (alpha.length() < 2) {
alpha = "0" + alpha;
}
toolBarColor = Color.parseColor("#" + alpha + "ff4c4b");
((MainActivity) getActivity()).setToolBarColor(toolBarColor);
}

toolBarAlpha是一个变化系数,乘以0xff得到一个新的alpha值然后拼接字符串生成一个新的color
想法是好的,但是实现起来太丑陋的,现在我们提供一种更好的实现方法

1
2
3
4
5
6
7
8
9
public static int getColorWithAlpha(int color, float ratio) {
int newColor = 0;
int alpha = Math.round(Color.alpha(color) * ratio);
int r = Color.red(color);
int g = Color.green(color);
int b = Color.blue(color);
newColor = Color.argb(alpha, r, g, b);
return newColor;
}

Android SDK已经给我们提供了提取颜色通道的方法,直接提取就好了。而我们关注的不仅仅是好看的代码,而是怎么实现的。

Color组成

先看color的组成代码:

1
2
3
public static int argb(int alpha, int red, int green, int blue) {
return (alpha << 24) | (red << 16) | (green << 8) | blue;
}

什么意思呢?一张图看懂

color
r的二进制向左移动16位,r << 16,g的二进制向左移动8位,而b的二进制则不需要移位操作。如果需要alpha通道,那么a的二进制向左移动24位。

提取颜色

知道了怎么组成也就好容易理解提取颜色通道

  1. blue:不需要移位,color&0xFF,由于高位还有其余通道值,所以高位要取0 &0xFF,剩余取blue。
  2. green:右移8位,相当于移位到blue的位置,原blue已经移出,然后与0xff相,(color >> 8) & 0xFF。
  3. red:原理同上 (color >> 16) & 0xFF;
  4. alpha:由于alpha在最高位,alpha移位操作如下
1
2
3
4
5
6
0xff000000,那其实二进制是
color :1111 1111 0000 0000 0000 0000 0000 0000
color >>24结果 :1111 1111 1111 1111 1111 1111 1111 1111
color >>>24结果:0000 0000 0000 0000 0000 0000 1111 1111

右移如果最高位为1那么左侧都补1,这样就导致生成的结果有问题,所以我们要用无符号右移操作,color >>> 24,右移完高位都补0,所以也不用&0xff。

总结

简单来说,Color都是位操作,在计算机的世界里,位移操作是最快的运算方式,并且对于内存的占用相对于基本数据类型也要有优势,比如表示状态,我们一般声明几个int值,但是有没有想过一个int类型就要占4byte=32bit,如果用位操作的话32bit基本就够用了,可以节省一些内存。

熟练掌握位移操作对于开发效率来说也会有相应的提高。在Android的代码中也是频繁的用到位移操作运用,比如刚刚收的一些状态操作,color操作等等。

参考

本文链接: http://w4lle.com/2016/05/22/Android-Color/

版权声明:本文为 w4lle 原创文章,可以随意转载,但必须在明确位置注明出处!
本文链接: http://w4lle.com/2016/05/22/Android-Color/