JavaME UI设计之渐变色处理

  •  
    移动应用的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);
           }
    }
    由于篇幅关系,原理类似的算法,就不在重复分析,效果如下图所示。
     
    评估该帖

 

你可能感兴趣的:(算法,UI,image,null,JavaME,colors)