移动应用的UI设计通常比较复杂,因为,需要同时考虑设备的内存状况、处理性能,一般情况,效果非常好的UI都需要很多图素,这样就增加了软件包的大小使得用户难以接受,比如,我们需要实现一个全屏幕渐变色的效果,如果选择用图片来实现,随都能做出来,并且也很简单,只需要美术准备好一张渐变色的图片,然后我们用程序drawImage显示上去即可,但是这张图片不仅增加了软件包的大小。而且如果我们需要动态更新一个这个渐变颜色也非常不方便(比如:在一个软件中,我们需要同时有一个水平方向的渐变和一个垂直方向的渐变,难道要准备两张图片吗?),因此,我们可以考虑使用程序直接来绘制渐变色。
JavaME中有一个函数drawRGB专门用来绘制一个颜色,该函数同能非常强大,在做UI设计时使用非常多,比如:需要调整应用中的一张图片的亮度等,都会使用这个函数,下面是该函数的具体用法:
drawRGB(int[] rgbData, int offset, int scanlength, int x, int y, int width, int height, boolean processAlpha)
offset:要绘制的数据在rgbData中的偏移,也就是起始点
scanlength:每一行起始点的数据在rgbData中的间隔
x: 表示区域开始的x坐标
y: 表示区域开始的y坐标
width:这个区域的宽度
height: 这个区域的高度
比如rgbData是一个16*16的颜色矩形。要绘制其中(2,2,4,4)的矩形到点(3,4)则代码如下:
drawRGB(rgbData,2,16,3,4,4,4,processAlpha)
最后的processAlpha设置成true,然后前面的颜色为ARGB是可以绘制半透明和透明色的,需要注意在部分机型上对于半透明及透明的支持。
在MIDP2.0的图片编程中,可以把图片理解为一个int[]数组,数组中的每个数据都与图片中的一个像素对应。数组中的int类型的数据被分为4个部分,每个部分由8bit字节构成,分别代表Alpha通道,red通道,green通道,blue通道。其中,rgb代表图片颜色的组成,A代表图片的透明度。1111 1111代表像素完全不透明,0000 0000代表像素完全透明,介于两者之间的则代表半透明像素。同样的,对于我们要绘制的一块渐变色的区域也可以理解为一个int[]数组,这样我们就只需要计算该数组中的数值为渐变色,然后调用drawRGB函数绘制即可。如下代码所示,我们将计算一个指定颜色的垂直方向的渐变颜色数组。
public final static int[] getRGBVColor(int color, int h) {
int[] rgb;
int RGB_L = h;
int nRgbData = RGB_L * 4;
int a;
rgb = new int[nRgbData];
for (int i = 0; i < RGB_L; i++) {
a = i;
if (a > 255) {
a = 255;
}
int col = color | (a << 24);
rgb[i * 4] = col;
rgb[i * 4 + 1] = col;
rgb[i * 4 + 2] = col;
rgb[i * 4 + 3] = col;
}
return rgb;
}
参数color为要渐变的颜色,h为渐变区域的高度,首先构建了一个int[]数组,长度为h*4,然后根据指定颜色改变其r,g,b通道形成新的颜色保存在该int[]数组中,接下来就是调用drawRGB函数来绘制出该数组中的数据即可。代码如下:
public final static void drawRGBVRect(Graphics g, int color, int x, int y,
int width, int height) {
int[] rgb = getRGBVColor(color, height);
for (int i = 0; i < width; i += 4) {
int nTemp = x + width - (i - x);
nTemp = nTemp > 4 ? 4 : nTemp;
g.drawRGB(rgb, 0, 4, i, y, nTemp, height, true);
}
}
绘制过程非常简单,通过一个for按照指定的宽度width进行循环绘制即可,比如使用如下代码:
CrystalRGB.drawRGBVRect(g, 0xff0000, 0, 0, 240, 320);
绘制一个240*320宽度和高度的渐变矩形框,绘制的效果如图1-1所示。
图1-1 垂直渐变颜色
当然,还有其他各种渐变色的绘制,原理都几乎一样,这里我们将一个沿水平方向渐变的代码贴出来,如下代码所示:
public final static int[] getRGBSColor(int color, int h) {
int[] rgb;
int RGB_L = h;
int nRgbData = RGB_L * 4;
rgb = new int[nRgbData];
int alpha = -127;
for (int i = 0; i < RGB_L; i++) {
alpha = -127 + i;
int col = color | (128 - alpha << 24);
rgb[i] = col;
rgb[i + RGB_L] = col;
rgb[i + RGB_L * 2] = col;
rgb[i + RGB_L * 3] = col;
}
return rgb;
}
public final static void drawRGBSRect(Graphics g, int color, int x, int y,
int width, int height) {
int[] rgb = getRGBSColor(color, width);
for (int by = y; by < y + height; by += 4) {
int nTemp = y + height - (by - y);
nTemp = nTemp > 4 ? 4 : nTemp;
g.drawRGB(rgb, 0, width, x, by, width, nTemp, true);
}
}
效果如图1-2所示。
1-2水平渐变颜色
最后,给大家列出了另外一种算法,原理差不多,但是可以用来实现某种特殊效果,这里是将生成的颜色数组,通过Image.createRGBImage函数创建为一个Image对象,然后通过drawImage函数将该Image对象绘制出来,并且该函数实现了指定在两种颜色之间的渐变,代码如下:
private static int[] retrieveRGBComponent(int color) {
int[] rgb = new int[3];
rgb[0] = (color & 0x00ff0000) >> 16;
rgb[1] = (color & 0x0000ff00) >> 8;
rgb[2] = (color & 0x000000ff);
return rgb;
}
private static int generateFromRGBComponent(int[] rgb) {
if (rgb == null || rgb.length != 3 || rgb[0] < 0 || rgb[0] > 255
|| rgb[1] < 0 || rgb[1] > 255 || rgb[2] < 0 || rgb[2] > 255)
return 0xfffff;
return rgb[0] << 16 | rgb[1] << 8 | rgb[2];
}
private static int[] generateTransitionalColor(int color1, int color2,int steps) {
int[] color1RGB = retrieveRGBComponent(color1);
int[] color2RGB = retrieveRGBComponent(color2);
if (steps < 3 || color1RGB == null || color2RGB == null)
return null;
int[] colors = new int[steps];
colors[0] = color1;
colors[colors.length - 1] = color2;
steps = steps - 2;
int redDiff = color2RGB[0] - color1RGB[0];
int greenDiff = color2RGB[1] - color1RGB[1];
int blueDiff = color2RGB[2] - color1RGB[2];
for (int i = 1; i < colors.length - 1; i++) {
colors[i] = generateFromRGBComponent(new int[] {
color1RGB[0] + redDiff * i / steps,
color1RGB[1] + greenDiff * i / steps,
color1RGB[2] + blueDiff * i / steps });
}
return colors;
}
public static void drawSelectedBackground(Graphics g, int x, int y, int width,
int height, int TransStart, int TransEnd) {
//
// 从左到右渐变
//
int[] line = generateTransitionalColor(TransStart, TransEnd, width);
//
Image lineImg = Image.createRGBImage(line, line.length, 1, false);
//
for (int i = 0; i < height; i++) {
//
g.drawImage(lineImg, x, y + i, Graphics.LEFT | Graphics.TOP);
//
}
// 从上到下渐变
int[] line = generateTransitionalColor(TransStart, TransEnd, height);
Image lineImg = Image.createRGBImage(line, 1, line.length, false);
for (int i = 0; i < width; i++) {
g.drawImage(lineImg, x + i, y, Graphics.LEFT | Graphics.TOP);
}
}
由于篇幅关系,原理类似的算法,就不在重复分析,效果如下图所示。
评估该帖