在运行时创建一个 NinePatch/NinePatchDrawable [英] Create a NinePatch/NinePatchDrawable in runtime

查看:54
本文介绍了在运行时创建一个 NinePatch/NinePatchDrawable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a requirement on my Android application that parts on the graphics should be customizable, by retrieving new colors and images from the server side. Some of these images are nine-patch images.

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

I can't find a way to create and display these nine-patch images (that have been retrieved over the network).

九个补丁图像被检索并作为位图保存在应用程序中.为了创建一个 NinePatchDrawable,您需要相应的NinePatch 或块(byte[]) 的 NinePatch.NinePatch 无法从资源加载,因为图像不存在于 /res/drawable/ 中.此外,为了创建 NinePatch,您需要 NinePatch 的块.所以,这一切都会深入到块中.
那么问题是,如何从现有位图(包含 NinePatch 信息)格式化/生成块?

The nine-patch images are retrieved and kept in the application as Bitmaps. In order to create a NinePatchDrawable, you either need the corresponding NinePatch or the chunk (byte[]) of the NinePatch. The NinePatch can NOT be loaded from the Resources, since the images doesn't exist in /res/drawable/. Furthermore, in order to create the NinePatch, you need the chunk of the NinePatch. So, it all drills down to the chunk.
The question is then, how do one format/generate the chunk from an existing Bitmap (containing the NinePatch information)?

我搜索了 Android 源代码和网络,但似乎找不到任何此类示例.更糟糕的是,NinePatch 资源的所有解码似乎都是本机完成的.

I've searched through the Android source code and the Web and I can't seem to find any examples of this. To make things worse, all decoding of a NinePatch resources seem to be done natively.

有没有人遇到过这种问题?

Have anyone had any experiences with this kind of issue?

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

I'm targeting API level 4, if that is of importance.

推荐答案

getNin​​ePatchChunk 工作正常.它返回 null 因为你给了 Bitmap 一个源"ninepatch.它需要一个编译"的 Ninepatch 图像.

getNinePatchChunk works just fine. It returned null because you were giving Bitmap a "source" ninepatch. It needs a "compiled" ninepatch image.

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

There are two types of ninepatch file formats in the Android world ("source" and "compiled"). The source version is where you add the 1px transparency border everywhere-- when you compile your app into a .apk later, aapt will convert your *.9.png files to the binary format that Android expects. This is where the png file gets its "chunk" metadata. (read more)

好的,现在进入正题(您正在听 DJ kanzure).

Okay, now down to business (you're listening to DJ kanzure).

  1. 客户端代码,类似于:

  1. Client code, something like this:

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);

  • 服务器端,你需要准备好你的图片.您可以使用 Android 二进制资源编译器.这使创建新 Android 项目的一些痛苦自动化,只是为了将一些 *.9.png 文件编译为 Android 原生格式.如果您要手动执行此操作,您基本上会创建一个项目并放入一些 *.9.png 文件(源"文件),将所有内容编译为 .apk 格式,解压缩 .apk 文件,然后找到 *.9.png 文件.9.png 文件,这就是您发送给客户的文件.

  • Server-side, you need to prepare your images. You can use the Android Binary Resource Compiler. This automates some of the pain away from creating a new Android project just to compile some *.9.png files into the Android native format. If you were to do this manually, you would essentially make a project and throw in some *.9.png files ("source" files), compile everything into the .apk format, unzip the .apk file, then find the *.9.png file, and that's the one you send to your clients.

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

    Also: I don't know if BitmapFactory.decodeStream knows about the npTc chunk in these png files, so it may or may not be treating the image stream correctly. The existence of Bitmap.getNinePatchChunk suggests that BitmapFactory might-- you could go look it up in the upstream codebase.

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

    In the event that it does not know about the npTc chunk and your images are being screwed up significantly, then my answer changes a little.

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

    Instead of sending the compiled ninepatch images to the client, you write a quick Android app to load compiled images and spit out the byte[] chunk. Then, you transmit this byte array to your clients along with a regular image-- no transparent borders, not the "source" ninepatch image, not the "compiled" ninepatch image. You can directly use the chunk to create your object.

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

    Another alternative is to use object serialization to send ninepatch images (NinePatch) to your clients, such as with JSON or the built-in serializer.

    编辑如果你真的,真的需要构建你自己的块字节数组,我会从查看do_9patchisNinePatchChunkRes_png_9patch 和 Res_png_9patch::serialize().还有一个来自 Dmitry Skiba 的自制 npTc 块阅读器.我无法发布链接,所以如果有人可以编辑我的答案,那就太好了.

    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() in ResourceTypes.cpp. There's also a home-made npTc chunk reader from Dmitry Skiba. I can't post links, so if someone can edit my answer that would be cool.

    do_9 补丁: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

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

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

    struct 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

    Dmitry Skiba stuff: http://code.google.com/p/android4me/source/browse/src/android/graphics/Bitmap.java

    这篇关于在运行时创建一个 NinePatch/NinePatchDrawable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆