在黑莓中绘制径向渐变?

时间:2013-01-24 05:25:56

标签: blackberry java-me

如何在BlackBerry中绘制径向渐变按钮?我在BlackBerry支持论坛上找到了“Drawing Radial Gradients”。我能够自己实现的是线性渐变。

1 个答案:

答案 0 :(得分:1)

这有点棘手。在场地背景上绘制线性渐变很容易。在场背景上绘制径向渐变更难。在按钮上执行操作更难。

首先,您链接到的示例确实看起来非常糟糕。该代码的最大问题是它使用Graphics.drawArc()来构造同心圆(线)之外的渐变。这根本不顺利。

您需要做的最大改进是使用Graphics.fillArc()代替,这看起来会更顺畅(尽管可能会对此产生性能影响......)。

您的问题没有说明在聚焦时您希望按钮看起来如何,或者角落是否需要四舍五入。这就是一些困难所在。

如果你只是扩展RIM ButtonField类,你可能会遇到焦点和边缘效果的默认绘图。可能需要在一个新的,从头开始编写的按钮字段中直接扩展基类Field类。我不一定建议您自己完成所有这些操作,因为按钮需要焦点处理,点击处理等。您可能应该从BlackBerry AdvancedUI开源库中的BaseButtonField开始。

我已经为你做了原型,使用该类作为基础。 (因此,如果您使用此文件,则需要下载并在项目中包含该源文件。)

我创建了一个GradientButtonField子类:

   private class GradientButtonField extends BaseButtonField {

      private int startR;
      private int startG;
      private int startB;

      private int endR;
      private int endG;
      private int endB;

      /** the maximum distance from the field's center, in pixels */
      private double rMax = -1.0;

      private int width;
      private int height;

      private String label;
      private int fontColor;

      /**
       * Create a gradient button field
       * @param startColor the integer Color code to use at the button center
       * @param endColor the integer Color code to use at the button edges
       * @param label the text to show on the button
       * @param fontColor color for label text
       */
      public GradientButtonField (int startColor, int endColor, String label, int fontColor) {         
         // record start and end color R/G/B components, to 
         //  make intermediate math easier
         startR = (startColor >> 16) & 0xFF;
         startG = (startColor >> 8) & 0xFF;
         startB = startColor & 0xFF;
         endR = (endColor >> 16) & 0xFF;
         endG = (endColor >> 8) & 0xFF;
         endB = endColor & 0xFF;
         this.label = label;
         this.fontColor = fontColor;
      }

      public String getLabel() {
         return label;
      }

      protected void layout(int w, int h) {        
         width = Math.min(Display.getWidth(), w);
         height = Math.min(Display.getHeight(), h);
         if (rMax < 0.0) {
            rMax = Math.sqrt((width * width)/4.0 + (height * height)/4.0);
         }
         setExtent(width, height);  
      }

      private int getColor(double scale, boolean highlighted) {
         int r = (int)(scale * (endR - startR)) + startR;
         int g = (int)(scale * (endG - startG)) + startG;
         int b = (int)(scale * (endB - startB)) + startB;

         if (highlighted) {
            // just brighten the color up a bit
            r = (int)Math.min(255, r * 1.5);
            g = (int)Math.min(255, g * 1.5);
            b = (int)Math.min(255, b * 1.5);
         }
         return (65536 * r + 256 * g + b);         
      }

      protected void paint(Graphics graphics) {
         int oldColor = graphics.getColor();

         // we must loop from the outer edge, in, to draw
         //  concentric circles of decreasing radius, and 
         //  changing color
         for (int radius = (int)rMax; radius >= 0; radius--) {
            double scale = ((double)radius) / rMax;
            boolean focused = (getVisualState() == Field.VISUAL_STATE_FOCUS);
            graphics.setColor(getColor(scale, focused));
            int x = width / 2 - radius;
            int y = height / 2 - radius;
            graphics.fillArc(x, y, 2 * radius, 2 * radius, 0, 360);           
         }

         String text = getLabel();
         graphics.setColor(fontColor);
         graphics.drawText(text, 
               (width - getFont().getAdvance(text)) / 2,
               (height - getFont().getHeight()) / 2);

         // reset graphics object
         graphics.setColor(oldColor);
      }         
   }

要使用此功能,包含该按钮的Manager将需要在其sublayout()实现中约束按钮的大小。或者,您可以修改我的GradientButtonField课程以硬编码特定尺寸(通过getPreferredWidth()layout()等)或任何您想要的内容。

  final Field button1 = new GradientButtonField(Color.DARKGRAY, Color.BLUE, 
        "Click Me!", Color.WHITE);
  final Field button2 =  new GradientButtonField(Color.DARKGRAY, Color.BLUE, 
        "Click Me, Too!", Color.WHITE);

  Manager mgr = new Manager(Manager.NO_VERTICAL_SCROLL) {

     public int getPreferredHeight() {
        return Display.getHeight();
     }
     public int getPreferredWidth() {
        return Display.getWidth();
     }

     protected void sublayout(int maxWidth, int maxHeight) {
        setExtent(getPreferredWidth(), getPreferredHeight());

        layoutChild(button1, 160, 80);
        setPositionChild(button1, 20, 50);

        layoutChild(button2, 120, 60);
        setPositionChild(button2, 20, 150);
     }
  };

  button1.setChangeListener(new FieldChangeListener() {
     public void fieldChanged(Field field, int context) {
        Dialog.alert("clicked!");               
     }
  });

  mgr.add(button1);
  mgr.add(button2);
  add(mgr);

我没有绕过角落,因为这有点工作。根据您放置这些按钮的背景类型,最简单的方法是创建一个PNG 蒙版图像(在您喜欢的绘图程序中),这个图像大部分是透明的,然后只是填充角落掩盖了它下方渐变的角落。然后,在上面的Graphics.drawBitmap()方法中使用paint(),在之后使用绘制径向渐变。

对于焦点突出显示,我只需输入一些简单的代码即可在按钮聚焦时使颜色变亮。再一次,你没有说出你想要的东西,所以我只是做了一些简单的事情。

这是上面代码的结果。底部按钮是聚焦的:

enter image description here