最近在Swing中使用.9图片,用到了NinePatchChunk.java文件,但是发现有时会出现无法完美展示的情况,决定修复一下这个问题,顺便研究一些.9的绘制过程

通过分析发现draw函数先是计算出固定宽高大小,再计算出拉升区域大小,最后遍历固定大小和拉伸大小的矩形,进行拉升的覆盖。

在分析的时候发现,我所遇到的bug是通过计算固定高得到拉伸高度时,如果有一边被填满就无法计算准确这个值引起的。

这里:

        int remainderHorizontal = 0;int remainderVertical = 0;if (mFixed.size() > 0) {int start = mFixed.get(0).y;for (Rectangle rect : mFixed) {if (rect.y > start) {endRow = true;measuredWidth = true;}if (!measuredWidth) {remainderHorizontal += rect.width;}if (endRow) {remainderVertical += rect.height;endRow = false;start = rect.y;}}}data.mRemainderHorizontal = scaledWidth - remainderHorizontal;data.mRemainderVertical = scaledHeight - remainderVertical;

解决方法之一就是不使用填满边的.9图。当然也可以修改代码来解决。

绘制的代码:

    private void draw(BufferedImage image, Graphics2D graphics2D, int x, int y, int scaledWidth,int scaledHeight) {if (scaledWidth <= 1 || scaledHeight <= 1) {return;}Graphics2D g = (Graphics2D)graphics2D.create();g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);try {if (mPatches.size() == 0) {g.drawImage(image, x, y, scaledWidth, scaledHeight, null);return;}g.translate(x, y);x = y = 0;DrawingData data = computePatches(scaledWidth, scaledHeight);int fixedIndex = 0;int horizontalIndex = 0;int verticalIndex = 0;int patchIndex = 0;boolean hStretch;boolean vStretch;float vWeightSum = 1.0f;float vRemainder = data.mRemainderVertical;vStretch = mVerticalStartWithPatch;while (y < scaledHeight - 1) {hStretch = mHorizontalStartWithPatch;int height = 0;float vExtra = 0.0f;float hWeightSum = 1.0f;float hRemainder = data.mRemainderHorizontal;while (x < scaledWidth - 1) {Rectangle r;if (!vStretch) {if (hStretch) {r = mHorizontalPatches.get(horizontalIndex++);float extra = r.width / data.mHorizontalPatchesSum;int width = (int) (extra * hRemainder / hWeightSum);hWeightSum -= extra;hRemainder -= width;g.drawImage(image, x, y, x + width, y + r.height, r.x, r.y,r.x + r.width, r.y + r.height, null);x += width;} else {r = mFixed.get(fixedIndex++);g.drawImage(image, x, y, x + r.width, y + r.height, r.x, r.y,r.x + r.width, r.y + r.height, null);x += r.width;}height = r.height;} else {if (hStretch) {r = mPatches.get(patchIndex++);vExtra = r.height / data.mVerticalPatchesSum;height = (int) (vExtra * vRemainder / vWeightSum);float extra = r.width / data.mHorizontalPatchesSum;int width = (int) (extra * hRemainder / hWeightSum);hWeightSum -= extra;hRemainder -= width;g.drawImage(image, x, y, x + width, y + height, r.x, r.y,r.x + r.width, r.y + r.height, null);x += width;} else {r = mVerticalPatches.get(verticalIndex++);vExtra = r.height / data.mVerticalPatchesSum;height = (int) (vExtra * vRemainder / vWeightSum);g.drawImage(image, x, y, x + r.width, y + height, r.x, r.y,r.x + r.width, r.y + r.height, null);x += r.width;}}hStretch = !hStretch;}x = 0;y += height;if (vStretch) {vWeightSum -= vExtra;vRemainder -= height;}vStretch = !vStretch;}} finally {g.dispose();}}

计算patch长度和固定长度的remainder的代码

    private DrawingData computePatches(int scaledWidth, int scaledHeight) {DrawingData data = new DrawingData();boolean measuredWidth = false;boolean endRow = true;int remainderHorizontal = 0;int remainderVertical = 0;if (mFixed.size() > 0) {int start = mFixed.get(0).y;for (Rectangle rect : mFixed) {if (rect.y > start) {endRow = true;measuredWidth = true;}if (!measuredWidth) {remainderHorizontal += rect.width;}if (endRow) {remainderVertical += rect.height;endRow = false;start = rect.y;}}}data.mRemainderHorizontal = scaledWidth - remainderHorizontal;data.mRemainderVertical = scaledHeight - remainderVertical;data.mHorizontalPatchesSum = 0;if (mHorizontalPatches.size() > 0) {int start = -1;for (Rectangle rect : mHorizontalPatches) {if (rect.x > start) {data.mHorizontalPatchesSum += rect.width;start = rect.x;}}} else {int start = -1;for (Rectangle rect : mPatches) {if (rect.x > start) {data.mHorizontalPatchesSum += rect.width;start = rect.x;}}}data.mVerticalPatchesSum = 0;if (mVerticalPatches.size() > 0) {int start = -1;for (Rectangle rect : mVerticalPatches) {if (rect.y > start) {data.mVerticalPatchesSum += rect.height;start = rect.y;}}} else {int start = -1;for (Rectangle rect : mPatches) {if (rect.y > start) {data.mVerticalPatchesSum += rect.height;start = rect.y;}}}return data;}

转载于:https://www.cnblogs.com/TLightSky/p/3479961.html

NinePatchChunk.java分析相关推荐

  1. 利用Spring-Boot解析Excel、用Java分析Excel、告别手动输入用程序读取Excel

    利用Spring-Boot解析Excel.用Java分析Excel.告别手动输入用程序读取Excel 一.资源 java读取Excel文件 二.修改 (一)中的代码中的 import service. ...

  2. java 分析java死锁_Java死锁示例–如何分析死锁情况

    java 分析java死锁 死锁是两个线程或多个线程永远被阻塞的编程情况,这种情况发生在至少两个线程和两个或更多资源的情况下. 在这里,我编写了一个简单的程序,它将导致死锁情况,然后我们将看到如何对其 ...

  3. java 分析java死锁_有益的CountDownLatch和棘手的Java死锁

    java 分析java死锁 您是否曾经使用过java.util.concurrent.CountDownLatch ? 这是在两个或多个线程之间实现同步的非常方便的类,在该类中,一个或多个线程可以等待 ...

  4. JAVA分析命令:jps、jstack、jmap、jhat

    JAVA分析命令:jps.jstack.jmap.jhat jps 用来查看基于HotSpot JVM里面所有进程的具体状态, 包括进程ID,进程启动的路径等等.与unix上的ps类似,用来显示本地有 ...

  5. JAVA字符串功能,Java分析字符串功能

    Java分析字符串功能 package Date; import java.util.Scanner; import java.util.StringTokenizer; public class T ...

  6. Java 分析 程序CPU 占用高的原因

    Java 分析 程序CPU 占用高的原因 背景:最近突然发现线上测程序长时间CPU 占用过高.内存确没有什么消耗.这种情况下可以排除死锁(一般死锁之后,如果不是自旋锁的话,CPU 占用都不会很高),也 ...

  7. JAVA分析html算法(JAVA网页蜘蛛算法)

    近来有些朋友在做蜘蛛算法,或者在网页上面做深度的数据挖掘.但是遇到复杂而繁琐的html页面大家都望而却步.因为很难获取到相应的数据. 最古老的办法的是尝试用正则表达式,估计那么繁琐的东西得不偿失,浪费 ...

  8. 通过网页查看服务器算法,java分析html算法(java网页蜘蛛算法示例)

    遇到复杂而繁琐的html页面大家都望而却步.因为很难获取到相应的数据. 最古老的办法的是尝试用正则表达式,估计那么繁琐的东西得不偿失,浪费我们宝贵的时间. 第二个办法用开源组织htmlparser的包 ...

  9. 性能工具之Java分析工具BTrace入门

    文章目录 一.引言 二.BTrace是什么? 三.BTrace原理 四.安装配置 五.注意事项 六.使用示例 1.拦截一个普通方法 2.拦截构造函数 3.拦截同名函数,以参数区分 4.拦截方法返回值 ...

  10. java 分析内存_Java 内存查看与分析

    1:gc日志输出 在jvm启动参数中加入 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimestamps -XX:+PrintGCApplication ...

最新文章

  1. 机器学习算法推导的较好例子
  2. 关于asp.net Session丢失问题的总结
  3. 世界机器人大会进入最后一天,最受市民关注的是它!
  4. 配电房来了个傻员工,改变了所有聪明的员工!
  5. 一篇讲清:数据采集中的安全与隐私
  6. 【机器学习基础】8个知识点,图解K-Means算法
  7. SQL Server 2008使用扩展事件进行高级故障排除
  8. ssl在线申请php源码,简易实现HTTPS之自动实现ssl
  9. mac中一一些常用的命令
  10. ajax-登陆+验证码
  11. vs2003 下载地址
  12. excel函数公式大全
  13. 用 Python 分析某医院药品销售案例!
  14. linux设备i2c优先级,Linux设备之I2C
  15. python 培训线下
  16. Oracle AutoVue 文件查看器Server服务器版安装及要求
  17. 动态修改svg图片颜色
  18. 将低版本CAD图纸转换成2018版本应该如何操作?
  19. 第七篇章——垃圾回收概念及相关算法
  20. 串行外设接口(Serial Peripheral Interface, SPI)逻辑设计部分 - spi_slave

热门文章

  1. 关于http-server的备选方案-- browser-sync
  2. Android中SQLite,ContentProvider和ContentResolver的使用(一)
  3. [bzoj3668][Noi2014]起床困难综合症/[洛谷3613]睡觉困难综合症
  4. 敲一下enter键,完成iOS的打包工作
  5. 4.3 createjs
  6. C和C++函数调用约定的区别
  7. jsoncpp用法简述
  8. 自写的简单屏蔽特定字符的TextBox和数字TextBox
  9. Java开发笔记(一百三十五)Swing的文件对话框
  10. 记一次nodemanager无法启动的情况