一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

JavaFX实现android中的9patch功能

时间:2016-06-02 编辑:简简单单 来源:一聚教程网

 9patch是android中直接支持的一个特性。在做背景图片和游戏中是比较常见的一种技术。在css中做背景很常见。其原理就是把一张图切成9块(9patch),如下图(比较懒,直接引用自网络):

9patch

保持1、3、7、9区域图片分别在新生成图片的左上角、右上角、左下角、右下角,2、8区域做repeat-x操作,4、6区域做repeat-y操作,5区域做repeat-x-y操作。这样即可解决图片自适应大小问题。而android中的9patch在原图片的上下左右分别添加了一个像素,上图产生的4条黑色线条,这样即可决定9区域的宽高大小了,其中右边和底部的黑色线条为决定内容部分,其实也没那神秘。

  JavaFX中没有这个强大功能,不过知道了原理,这里本人实现了一个javafx版,完全满足日常开发工作:

 代码如下 复制代码

/**
 * javafx实现android的9patch
 *
 * @author zhou
 *
 */
public final class NinePatch{
  private Image origin;
  private int top;
  private int right;
  private int bottom;
  private int left;

  public NinePatch(Image origin, int topRightBottomLeft){
    this(origin, topRightBottomLeft, topRightBottomLeft);
  }

  public NinePatch(Image origin, int topBottom, int leftRight){
    this(origin, topBottom, leftRight, topBottom, leftRight);
  }

  public NinePatch(Image origin, int top, int right, int bottom, int left){
    if(left + right > origin.getWidth())
      throw new IllegalArgumentException("left add right must less than origin width");

    if(top + bottom > origin.getHeight())
      throw new IllegalArgumentException("top add bottom must less than origin height");

    this.origin = origin;
    this.top = top;
    this.right = right;
    this.bottom = bottom;
    this.left = left;
  }

  /**
   * 生成指定宽高图片
   *
   * @param scaledWidth
   * @param scaledHeight
   * @return
   */
  public Image generate(int scaledWidth, int scaledHeight){
    WritableImage result = new WritableImage(scaledWidth, scaledHeight);
    PixelReader reader = origin.getPixelReader();
    PixelWriter writer = result.getPixelWriter();
    int originHCenterWidth = (int) origin.getWidth() - right - left;
    int originVCenterWidth = (int) origin.getHeight() - top - bottom;

    /* first row */
    writer.setPixels(0, 0, left, top, reader, 0, 0);
    for(int y = 0; y < top; y++){
      for(int x = left; x < scaledWidth - right; x++){
        writer.setArgb(x, y, reader.getArgb(left + (x - left) % originHCenterWidth, y));
      }
    }

    writer.setPixels(scaledWidth - right, 0, right, top, reader, (int) origin.getWidth() - right, 0);

    /* second row */
    for(int y = top; y < scaledHeight - bottom; y++){
      for(int x = 0; x < left; x++){
        writer.setArgb(x, y, reader.getArgb(x, top + (y - top) % originVCenterWidth));
      }
    }

    for(int y = top; y < scaledHeight - bottom; y++){
      for(int x = left; x < scaledWidth - right; x++){
        writer.setArgb(x, y,
            reader.getArgb(left + (x - left) % originHCenterWidth, top + (y - top) % originVCenterWidth));
      }
    }

    for(int y = top; y < scaledHeight - bottom; y++){
      for(int x = scaledWidth - right; x < scaledWidth; x++){
        writer.setArgb(x, y,
            reader.getArgb((int) origin.getWidth() + x - scaledWidth, top + (y - top) % originVCenterWidth));
      }
    }

    /* third row */
    writer.setPixels(0, scaledHeight - bottom, left, bottom, reader, 0, (int) origin.getHeight() - bottom);
    for(int y = scaledHeight - bottom; y < scaledHeight; y++){
      for(int x = left; x < scaledWidth - right; x++){
        writer.setArgb(x, y,
            reader.getArgb(left + (x - left) % originHCenterWidth, (int) origin.getHeight() + y - scaledHeight));
      }
    }
    writer.setPixels(scaledWidth - right, scaledHeight - bottom, right, bottom, reader,
        (int) origin.getWidth() - right, (int) origin.getHeight() - bottom);

    return result;
  }

  /**
   *
   * @param gc
   * @param x
   * @param y
   * @param scaledWidth
   * @param scaledWidth
   */
  public void draw(GraphicsContext gc, int x, int y, int scaledWidth, int scaledHeight){
    gc.drawImage(generate(scaledWidth, scaledHeight), x, y);
  }

}

这里没有使用黑色像素条(原始)的方式实现,因为知道了top、right、bottom、left就可以确定一个图片的9块区域了,后面就是做repeat操作了。

后面也很容易实现类似google的不指定topRightBottomLeft方式直接从xxx.9.png加载的功能。

热门栏目