在运行时创建一个 NinePatch/NinePatchDrawable

新手上路,请多包涵

我对我的 Android 应用程序有一个要求,即图形上的部分应该是可定制的,通过从服务器端检索新的颜色和图像。其中一些图像是九块图像。

我找不到创建和显示这些九补丁图像(已通过网络检索)的方法。

九个补丁图像被检索并作为位图保存在应用程序中。为了创建 NinePatchDrawable ,您需要相应的 NinePatch 或 NinePatch 的块 ( byte[] )。 NinePatch 无法从资源中加载,因为图像不存在于 /res/drawable/ 中。此外,为了创建 NinePatch,您需要 NinePatch 的块。所以,这一切都深入到大块。

那么问题是,如何从现有位图(包含 NinePatch 信息)格式化/生成块?

我搜索了 Android 源代码和 Web,但似乎找不到任何相关示例。更糟糕的是,NinePatch 资源的所有解码似乎都是本地完成的。

有没有人有过这种问题的经验?

如果这很重要,我的目标是 API 级别 4。

原文由 jacob11 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 856
1 个回答

getNinePatchChunk 工作正常。它返回 null,因为你给了 Bitmap 一个“源”ninepatch。它需要一个“已编译”的 ninepatch 图像。

Android 世界中有两种 ninepatch 文件格式(“源”和“编译”)。源版本是你在任何地方添加 1px 透明边框的地方——当你稍后将你的应用程序编译成 .apk 时,aapt 会将你的 *.9.png 文件转换为 Android 期望的二进制格式。这是 png 文件获取其“块”元数据的地方。 ( 阅读更多

好的,现在进入正题。

  1. 客户端代码,像这样:
    InputStream stream = .. //whatever
   Bitmap bitmap = BitmapFactory.decodeStream(stream);
   byte[] chunk = bitmap.getNinePatchChunk();
   boolean result = NinePatch.isNinePatchChunk(chunk);
   NinePatchDrawable patchy = new NinePatchDrawable(bitmap, chunk, new Rect(), null);

  1. 服务器端,您需要准备图像。您可以使用 Android Binary Resource Compiler 。这会自动避免创建新的 Android 项目只是为了将一些 *.9.png 文件编译成 Android 本机格式的痛苦。如果您手动执行此操作,您实际上会创建一个项目并放入一些 *.9.png 文件(“源”文件),将所有内容编译为 .apk 格式,解压缩 .apk 文件,然后找到 *.9.png 文件。 9.png 文件,这就是您发送给客户的文件。

另外:我不知道 BitmapFactory.decodeStream 是否知道这些 png 文件中的 npTc 块,因此它可能会或可能不会正确处理图像流。 Bitmap.getNinePatchChunk 的存在表明 BitmapFactory 可能-- 您可以在上游代码库中查找它。

如果它不知道 npTc 块并且您的图像被严重搞砸了,那么我的答案会稍微改变。

您无需将编译的 ninepatch 图像发送到客户端,而是编写一个快速的 Android 应用程序来加载编译的图像并吐出 byte[] 块。然后,您将此字节数组连同常规图像一起传输给您的客户——没有透明边框,不是“源”ninepatch 图像,也不是“编译”ninepatch 图像。您可以直接使用块来创建您的对象。

另一种方法是使用对象序列化将 ninepatch 图像 ( NinePatch ) 发送到您的客户端,例如使用 JSON 或内置序列化程序。

Edit If you really, really need to construct your own chunk byte array, I would start by looking at do_9patch , isNinePatchChunk , Res_png_9patch and Res_png_9patch::serialize() 在 ResourceTypes.cpp 中。还有一个来自 Dmitry Skiba 的自制 npTc 块读取器。我不能发布链接,所以如果有人可以编辑我的答案那会很酷。

do_9patch: https ://android.googlesource.com/platform/frameworks/base/+/gingerbread/tools/aapt/Images.cpp

isNinePatchChunk: http ://netmite.com/android/mydroid/1.6/frameworks/base/core/jni/android/graphics/NinePatch.cpp

结构 Res_png_9patch: https ://scm.sipfoundry.org/rep/sipX/main/sipXmediaLib/contrib/android/android_2_0_headers/frameworks/base/include/utils/ResourceTypes.h

德米特里斯基巴的东西: http ://code.google.com/p/android4me/source/browse/src/android/graphics/Bitmap.java

原文由 kanzure 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题