Android 使用远程下载的.9图片
众所周知,android的.9图片可以实现矢量拉伸,但是资源文件却被限制在本地而无法使用远端文件。
作者今天遇到了同样的问题,查看了一下android源码,发现NinePatch和NinePatchDrawable这两个玩意儿,.9图片最终的绘制是通过他们来实现的,那么问题来了,我只需要new出这两个东西不就OK了吗?so,我查看了一下构造函数,别的都好说,Chunk是什么鬼?还是个32字节的东西,按照作者经验,.9的黑边框应该是被解析成了这32字节的数据,然后Drawable按照这个规则来绘制画板的。查验多放资料,作者搞出了下面这个方法,你们可以参考下,可以生成Chunk字节数组,用他们就可以实现远端图片的.9了。
- public static byte[] readChunk(Bitmap resourceBmp) throws IOException {
- final int BM_W = resourceBmp.getWidth();
- final int BM_H = resourceBmp.getHeight();
- int xPointCount = 0;
- int yPointCount = 0;
- int xBlockCount = 0;
- int yBlockCount = 0;
- ByteArrayOutputStream bao = new ByteArrayOutputStream();
- for (int i = 0; i < 32; i++) {
- bao.write(0);
- }
- {
- int[] pixelsTop = new int[BM_W - 2];
- resourceBmp.getPixels(pixelsTop, 0, BM_W, 1, 0, BM_W - 2, 1);
- boolean topFirstPixelIsBlack = pixelsTop[0] == Color.BLACK;
- boolean topLastPixelIsBlack = pixelsTop[pixelsTop.length - 1] == Color.BLACK;
- int tmpLastColor = Color.TRANSPARENT;
- for (int i = 0, len = pixelsTop.length; i < len; i++) {
- if (tmpLastColor != pixelsTop[i]) {
- xPointCount++;
- writeInt(bao, i);
- tmpLastColor = pixelsTop[i];
- }
- }
- if (topLastPixelIsBlack) {
- xPointCount++;
- writeInt(bao, pixelsTop.length);
- }
- xBlockCount = xPointCount + 1;
- if (topFirstPixelIsBlack) {
- xBlockCount--;
- }
- if (topLastPixelIsBlack) {
- xBlockCount--;
- }
- }
- {
- int[] pixelsLeft = new int[BM_H - 2];
- resourceBmp.getPixels(pixelsLeft, 0, 1, 0, 1, 1, BM_H - 2);
- boolean firstPixelIsBlack = pixelsLeft[0] == Color.BLACK;
- boolean lastPixelIsBlack = pixelsLeft[pixelsLeft.length - 1] == Color.BLACK;
- int tmpLastColor = Color.TRANSPARENT;
- for (int i = 0, len = pixelsLeft.length; i < len; i++) {
- if (tmpLastColor != pixelsLeft[i]) {
- yPointCount++;
- writeInt(bao, i);
- tmpLastColor = pixelsLeft[i];
- }
- }
- if (lastPixelIsBlack) {
- yPointCount++;
- writeInt(bao, pixelsLeft.length);
- }
- yBlockCount = yPointCount + 1;
- if (firstPixelIsBlack) {
- yBlockCount--;
- }
- if (lastPixelIsBlack) {
- yBlockCount--;
- }
- }
- {
- for (int i = 0; i < xBlockCount * yBlockCount; i++) {
- writeInt(bao, NO_COLOR);
- }
- }
- byte[] data = bao.toByteArray();
- data[0] = 1;
- data[1] = (byte) xPointCount;
- data[2] = (byte) yPointCount;
- data[3] = (byte) (xBlockCount * yBlockCount);
- dealPaddingInfo(resourceBmp, data);
- return data;
- }
- private static void dealPaddingInfo(Bitmap bm, byte[] data) {
- { // padding left & padding right
- int[] bottomPixels = new int[bm.getWidth() - 2];
- bm.getPixels(bottomPixels, 0, bottomPixels.length, 1,
- bm.getHeight() - 1, bottomPixels.length, 1);
- for (int i = 0; i < bottomPixels.length; i++) {
- if (Color.BLACK == bottomPixels[i]) { // padding left
- writeInt(data, 12, i);
- break;
- }
- }
- for (int i = bottomPixels.length - 1; i >= 0; i--) {
- if (Color.BLACK == bottomPixels[i]) { // padding right
- writeInt(data, 16, bottomPixels.length - i - 2);
- break;
- }
- }
- }
- { // padding top & padding bottom
- int[] rightPixels = new int[bm.getHeight() - 2];
- bm.getPixels(rightPixels, 0, 1, bm.getWidth() - 1, 0, 1,
- rightPixels.length);
- for (int i = 0; i < rightPixels.length; i++) {
- if (Color.BLACK == rightPixels[i]) { // padding top
- writeInt(data, 20, i);
- break;
- }
- }
- for (int i = rightPixels.length - 1; i >= 0; i--) {
- if (Color.BLACK == rightPixels[i]) { // padding bottom
- writeInt(data, 24, rightPixels.length - i - 2);
- break;
- }
- }
- }
- }
- private static void writeInt(OutputStream out, int v) throws IOException {
- out.write((v >> 0) & 0xFF);
- out.write((v >> 8) & 0xFF);
- out.write((v >> 16) & 0xFF);
- out.write((v >> 24) & 0xFF);
- }
- private static void writeInt(byte[] b, int offset, int v) {
- b[offset + 0] = (byte) (v >> 0);
- b[offset + 1] = (byte) (v >> 8);
- b[offset + 2] = (byte) (v >> 16);
- b[offset + 3] = (byte) (v >> 24);
- }
- private static int getInt(byte[] bs, int from) {
- int b1 = bs[from + 0];
- int b2 = bs[from + 1];
- int b3 = bs[from + 2];
- int b4 = bs[from + 3];
- int i = b1 | (b2 << 8) | (b3 << 16) | b4 << 24;
- return i;
- }
调用的方法也很简单:
- NinePatch ninePatch = null;
- try {
- ninePatch = new NinePatch(bitmap,NinePatchUtils.readChunk(bitmap));
- } catch (IOException e) {
- e.printStackTrace();
- }
- NinePatchDrawable ninePatchDrawable = new NinePatchDrawable(getResources(),ninePatch);
- imageView.setBackgroundDrawable(ninePatchDrawable);
如此,大功告成。
Comments