访问排行榜
谷歌广告
谷歌广告
Android 使用远程下载的.9图片
Author zero | Posted 2016-11-18 11:00:00

Android 使用远程下载的.9图片

众所周知,android的.9图片可以实现矢量拉伸,但是资源文件却被限制在本地而无法使用远端文件。

作者今天遇到了同样的问题,查看了一下android源码,发现NinePatch和NinePatchDrawable这两个玩意儿,.9图片最终的绘制是通过他们来实现的,那么问题来了,我只需要new出这两个东西不就OK了吗?so,我查看了一下构造函数,别的都好说,Chunk是什么鬼?还是个32字节的东西,按照作者经验,.9的黑边框应该是被解析成了这32字节的数据,然后Drawable按照这个规则来绘制画板的。查验多放资料,作者搞出了下面这个方法,你们可以参考下,可以生成Chunk字节数组,用他们就可以实现远端图片的.9了。

  1. public static byte[] readChunk(Bitmap resourceBmp) throws IOException {
  2. final int BM_W = resourceBmp.getWidth();
  3. final int BM_H = resourceBmp.getHeight();
  4.  
  5. int xPointCount = 0;
  6. int yPointCount = 0;
  7. int xBlockCount = 0;
  8. int yBlockCount = 0;
  9.  
  10. ByteArrayOutputStream bao = new ByteArrayOutputStream();
  11. for (int i = 0; i < 32; i++) {
  12. bao.write(0);
  13. }
  14.  
  15. {
  16. int[] pixelsTop = new int[BM_W - 2];
  17. resourceBmp.getPixels(pixelsTop, 0, BM_W, 1, 0, BM_W - 2, 1);
  18. boolean topFirstPixelIsBlack = pixelsTop[0] == Color.BLACK;
  19. boolean topLastPixelIsBlack = pixelsTop[pixelsTop.length - 1] == Color.BLACK;
  20. int tmpLastColor = Color.TRANSPARENT;
  21. for (int i = 0, len = pixelsTop.length; i < len; i++) {
  22. if (tmpLastColor != pixelsTop[i]) {
  23. xPointCount++;
  24. writeInt(bao, i);
  25. tmpLastColor = pixelsTop[i];
  26. }
  27. }
  28. if (topLastPixelIsBlack) {
  29. xPointCount++;
  30. writeInt(bao, pixelsTop.length);
  31. }
  32. xBlockCount = xPointCount + 1;
  33. if (topFirstPixelIsBlack) {
  34. xBlockCount--;
  35. }
  36. if (topLastPixelIsBlack) {
  37. xBlockCount--;
  38. }
  39. }
  40.  
  41. {
  42. int[] pixelsLeft = new int[BM_H - 2];
  43. resourceBmp.getPixels(pixelsLeft, 0, 1, 0, 1, 1, BM_H - 2);
  44. boolean firstPixelIsBlack = pixelsLeft[0] == Color.BLACK;
  45. boolean lastPixelIsBlack = pixelsLeft[pixelsLeft.length - 1] == Color.BLACK;
  46. int tmpLastColor = Color.TRANSPARENT;
  47. for (int i = 0, len = pixelsLeft.length; i < len; i++) {
  48. if (tmpLastColor != pixelsLeft[i]) {
  49. yPointCount++;
  50. writeInt(bao, i);
  51. tmpLastColor = pixelsLeft[i];
  52. }
  53. }
  54. if (lastPixelIsBlack) {
  55. yPointCount++;
  56. writeInt(bao, pixelsLeft.length);
  57. }
  58. yBlockCount = yPointCount + 1;
  59. if (firstPixelIsBlack) {
  60. yBlockCount--;
  61. }
  62. if (lastPixelIsBlack) {
  63. yBlockCount--;
  64. }
  65. }
  66.  
  67. {
  68. for (int i = 0; i < xBlockCount * yBlockCount; i++) {
  69. writeInt(bao, NO_COLOR);
  70. }
  71. }
  72.  
  73. byte[] data = bao.toByteArray();
  74. data[0] = 1;
  75. data[1] = (byte) xPointCount;
  76. data[2] = (byte) yPointCount;
  77. data[3] = (byte) (xBlockCount * yBlockCount);
  78. dealPaddingInfo(resourceBmp, data);
  79. return data;
  80. }
  81.  
  82. private static void dealPaddingInfo(Bitmap bm, byte[] data) {
  83. { // padding left & padding right
  84. int[] bottomPixels = new int[bm.getWidth() - 2];
  85. bm.getPixels(bottomPixels, 0, bottomPixels.length, 1,
  86. bm.getHeight() - 1, bottomPixels.length, 1);
  87. for (int i = 0; i < bottomPixels.length; i++) {
  88. if (Color.BLACK == bottomPixels[i]) { // padding left
  89. writeInt(data, 12, i);
  90. break;
  91. }
  92. }
  93. for (int i = bottomPixels.length - 1; i >= 0; i--) {
  94. if (Color.BLACK == bottomPixels[i]) { // padding right
  95. writeInt(data, 16, bottomPixels.length - i - 2);
  96. break;
  97. }
  98. }
  99. }
  100. { // padding top & padding bottom
  101. int[] rightPixels = new int[bm.getHeight() - 2];
  102. bm.getPixels(rightPixels, 0, 1, bm.getWidth() - 1, 0, 1,
  103. rightPixels.length);
  104. for (int i = 0; i < rightPixels.length; i++) {
  105. if (Color.BLACK == rightPixels[i]) { // padding top
  106. writeInt(data, 20, i);
  107. break;
  108. }
  109. }
  110. for (int i = rightPixels.length - 1; i >= 0; i--) {
  111. if (Color.BLACK == rightPixels[i]) { // padding bottom
  112. writeInt(data, 24, rightPixels.length - i - 2);
  113. break;
  114. }
  115. }
  116. }
  117. }
  118.  
  119. private static void writeInt(OutputStream out, int v) throws IOException {
  120. out.write((v >> 0) & 0xFF);
  121. out.write((v >> 8) & 0xFF);
  122. out.write((v >> 16) & 0xFF);
  123. out.write((v >> 24) & 0xFF);
  124. }
  125.  
  126. private static void writeInt(byte[] b, int offset, int v) {
  127. b[offset + 0] = (byte) (v >> 0);
  128. b[offset + 1] = (byte) (v >> 8);
  129. b[offset + 2] = (byte) (v >> 16);
  130. b[offset + 3] = (byte) (v >> 24);
  131. }
  132.  
  133. private static int getInt(byte[] bs, int from) {
  134. int b1 = bs[from + 0];
  135. int b2 = bs[from + 1];
  136. int b3 = bs[from + 2];
  137. int b4 = bs[from + 3];
  138. int i = b1 | (b2 << 8) | (b3 << 16) | b4 << 24;
  139. return i;
  140. }

调用的方法也很简单:

  1. NinePatch ninePatch = null;
  2. try {
  3. ninePatch = new NinePatch(bitmap,NinePatchUtils.readChunk(bitmap));
  4. } catch (IOException e) {
  5. e.printStackTrace();
  6. }
  7. NinePatchDrawable ninePatchDrawable = new NinePatchDrawable(getResources(),ninePatch);
  8. imageView.setBackgroundDrawable(ninePatchDrawable);

如此,大功告成。

Android+GoLang+SprintBoot探讨群:186305789(疯狂的程序员),绝影大神在等你

个人兴趣网站:zero接码平台

个人兴趣网站:猿指


Comments