我正在创建一个复合自定义控件。该控件由底部的单个元素和顶部的未知数量的元素组成。这些元素中的每一个的背景都是一个 StateListDrawable,它定义了用于该元素的每个状态的 NinePatchDrawables。
当各个顶部元素更改其宽度以适应其内容时,正下方的底部元素区域也需要更改宽度以适应其内容。顶部元素的位置也可能向左或向右移动。
上面和下面的图像只是快速的模型,用于传达我需要实现的布局和行为。我不负责设计要使用的实际背景图像,但它们不会是统一的平面灰色。
我设法通过以下方式解决了这个重新调整大小问题的第一部分:
- 创建一个扩展 Drawable 的自定义类。
- 向类传递一个 NinePatchDrawables 数组,定义底部视图的各种潜在区域(例如 left_end、right_end、middle_below_control、middle_below_gap)。
- 在自定义类中更改每个边界以匹配上面的相关视图'
onBoundChange()
。 - 将我调整大小的 NinePatches 数组绘制到
onDraw()
. - 根据数组中 NinePatches 的填充设置底部视图的组合填充。
但是,此解决方案引发了许多问题:
- 您需要为底部视图的每个潜在区域提供 StateListDrawables。
- 您需要为每个 StateListDrawables 中的每个状态提供单独的 NinePatch 图像。
- 您必须为底部视图设计一个图像,该图像被限制为在其宽度上非常均匀。
- 你需要护耳器和厚脸皮来应对平面设计师的所有呼喊。
我真正需要实现的是:
- 底部视图有一个 StateListDrawable。
- 为每个状态提取单个图像并将其分割成所需的部分。
- 为每个切片创建一个新的 NinePatchDrawable,应用上面视图中的数据块仅用于宽度。不是身高。
- 然后按照我上面之前的解决方案重新组合它们。
不幸的是,我们知道,您不能真正使用数据块。它是在编译时从源图像生成的,以创建 NinePatch 二进制文件。
可以在此处找到有关此类主题的更好答案之一。基于此,一个可能的折衷解决方案可能是:
- 对于每个顶部元素类型,让图形设计师提供一个额外的空白虚拟 NinePatch 源,具有相同的高度和宽度尺寸、相同的宽度填充和补丁定义,但具有他们想要的底部视图的高度填充和补丁定义。
getNinePatchChunk()
在相关的虚拟 NinePatch 编译资源上使用。- 将生成的数据块与相关的底部视图位图切片结合起来,使用
NinePatch(Bitmap bitmap, byte[] chunk, String srcName)
. - 忍受平面设计师的肮脏表情,但至少他们已经停止大喊大叫了。
这似乎是一种笨拙的做事方式。有没有更好、更有效的方法来实现所有必需的目标?
注意:当在应用程序中使用时,在滚动视图中可能有很多此自定义控件的实例,因此需要将嵌套布局保持在最低限度。