.9图可以使用draw9patch工具来制作,但一般生成好并编译好后,就不能再对.9图进行修改,如果需要对.9图进行缩放,那原.9的位置信息将会变得错乱。本文叙述如何在缩放后动态修改.9信息。
.9图的结构定义在/frameworks/base/include/androidfw/ResourceTypes.h中,其结构定义如下:
1 | struct Res_png_9patch |
开始的32个字节是.9图的一些描述信息,描述如下:
wasDeserialized: 是否非序列化,目前作用不明
numXDivs:x方向上的分隔数
numYDivs:y方向上的分隔数
numColors:颜色数
如
这一张.9图,这图经过编译后的数据结构为:
如上图所示,划线部分为.9图的chunk部分,红线部分描述的结构为Res_png_9patch的结构,即非序列化,x方向上存在两个分隔点,y方向上也存在两个分隔点,color数为9(每个区域对应一个颜色,X,Y各两个分隔点,将图划分成9份),xDivs与yDivs的位置指向为0;paddingLeft,paddingRight,paddingTop,paddingBottom都为0;colors的数据指向都为0。
从第32个字节开始,就开始了描述.9信息的数据位置了(图蓝色部分),四条蓝色线表示x与y方向上的.9位置信息,每个点的位置信息用4字节表示,如x方向上的两个点为(0x0000 0000 0000 0041,0x0000 0000 0000 0052),此为x方向上的缩放区域,(0x0000 0000 0000 0042,0x0000 0000 0000 0052)为y上的缩放区域(载入内存后会以大端表示)。
color部分定义每一块patch是否透明,上图9个patch都为0x00000001,即NO_COLOR,表示用图片填充,目前此值有什么特别的用法还不清楚(?)。
知道了这个数据结构后就可以对这部分的数据进行修改了。做法很简单,按x与y的缩放比例去计算点位置信息在缩放后的新位置。关键代码如下:
1 | int start = 32;//从32个字节后是.9的真正信息 |
基于这种思想,同样可以自己创建一个自定义的chunk,大小随意,然后使用NinePatchDrawable来对一个普通的图片资源进行.9处理。
写完了。