我正在创建一个复合自定义控件。该控件由底部的单个元素和顶部的未知数量的元素组成。每个元素的背景是StateListDrawable,它定义了用于该元素的每个状态的NinePatchDrawable。
由于单个顶部元素会改变其宽度以适合其内容,因此底部元素的正下方区域也需要更改宽度以适应。顶部元素的位置也可能向左或向右移动。
上面和下面的图片只是快速模型,以传达我需要实现的布局和行为。我不负责设计要使用的实际背景图像,但它们不是均匀的扁平灰色。
我设法通过以下方式解决了这个重新调整大小问题的第一部分:
onBoundChange()
”中更改每个界限以匹配上述相关视图。onDraw()
中的底部视图画布。这个解决方案虽然引发了许多问题:
我真正需要实现的目标是:
不幸的是,正如我们所知,你无法真正使用数据块。它是在编译时从源图像生成的,用于创建NinePatch二进制文件。
可以找到关于此类主题的更好答案之一here。基于此,可能的折衷解决方案可能是:
getNinePatchChunk()
。NinePatch(Bitmap bitmap, byte[] chunk, String srcName)
创建新的NinePatch。这似乎是一种笨拙的做事方式。是否有更好,更有效的方法来实现所有目标?
注意:在应用中使用时,滚动视图中可能会有许多此自定义控件的实例,因此需要将嵌套布局保持在最低限度。
答案 0 :(得分:0)
我终于想出了一种避免使用空白虚拟NinePatch源的方法,这是我上面的妥协解决方案。
基于这个excellent solution类似的问题,我编写了一个实用工具方法来从NinePatch资源中提取填充信息。使用它,我可以从相邻的NinePatch区域中提取必要的填充,并将它们应用到我的新切片。希望这对其他人有所帮助。
public static Rect getNinePatchPadding(Context context, int drawableId) {
Rect mPadding = new Rect();
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), drawableId);
final byte[] chunk = bm.getNinePatchChunk();
if (!NinePatch.isNinePatchChunk(chunk)) return null;
ByteBuffer byteBuffer = ByteBuffer.wrap(chunk).order(ByteOrder.nativeOrder());
// Skip to padding
for (int i = 0; i < 12; i++) {
byteBuffer.get();
}
mPadding.left = byteBuffer.getInt();
mPadding.top = byteBuffer.getInt();
mPadding.right = byteBuffer.getInt();
mPadding.bottom = byteBuffer.getInt();
return mPadding;
}