在运行时创建 NinePatch/NinePatchDrawable

发布于 2024-10-18 17:28:46 字数 717 浏览 7 评论 0原文

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

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

九个补丁图像被检索并作为位图保存在应用程序中。为了创建 NinePatchDrawable,您需要相应的 < a href="http://developer.android.com/reference/android/graphics/NinePatch.html" rel="noreferrer">NinePatch 或块 (byte[])九补丁。 NinePatch 无法从资源加载,因为 /res/drawable/ 中不存在图像。此外,为了创建 NinePatch,您需要 NinePatch 的块。因此,一切都深入到该块。
那么问题是,如何从现有位图(包含 NinePatch 信息)格式化/生成块?

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

有没有人有过此类问题的经验?

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

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

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

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?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

他夏了夏天 2024-10-25 17:28:46

getNin​​ePatchChunk 工作得很好。它返回 null,因为您为 Bitmap 提供了“源”ninepatch。它需要一个“编译的”ninepatch 图像。

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

好的,现在开始说正事。

  1. 客户端代码,如下所示:

    InputStream 流 = .. //随便
    位图 bitmap = BitmapFactory.decodeStream(stream);
    byte[] chunk = bitmap.getNin​​ePatchChunk();
    布尔结果 = NinePatch.isNinePatchChunk(chunk);
    NinePatchDrawable patchy = new NinePatchDrawable(位图, 块, new Rect(), null);
    
  2. 服务器端,您需要准备图像。您可以使用 Android 二进制资源编译器。这可以自动消除创建新 Android 项目的一些痛苦,只是将一些 *.9.png 文件编译为 Android 本机格式。如果您要手动执行此操作,您实际上需要创建一个项目并放入一些 *.9.png 文件(“源”文件),将所有内容编译为 .apk 格式,解压缩 .apk 文件,然后找到 *.9.png 文件。 9.png 文件,这就是您发送给客户的文件。

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

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

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

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

编辑如果您真的非常需要构建自己的块字节数组,我会首先查看do_9patchisNinePatchChunkRes_png_9patch ResourceTypes.cpp 中的Res_png_9patch::serialize()。还有 Dmitry Skiba 自制的 npTc 块读取器。我无法发布链接,所以如果有人可以编辑我的答案那就太好了。

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

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

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

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

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)

Okay, now down to business.

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

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.

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.

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.

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

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_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

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

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

风月客 2024-10-25 17:28:46

如果您需要动态创建 9Patches,请查看我制作的要点: https://gist.github.com/4391807

你可以向它传递任何位图,然后给它提供类似于 iOS 的上限插入。

If you need to create 9Patches on the fly check out this gist I made: https://gist.github.com/4391807

You pass it any bitmap and then give it cap insets similar to iOS.

葮薆情 2024-10-25 17:28:46

我创建了一个工具来从(未编译的)NinePatch 位图创建 NinePatchDrawable。
请参阅 https://gist.github.com/knight9999/86bec38071a9e0a781ee

方法
NinePatchDrawable createNinePatchDrawable(Resources res, Bitmap bitmap)
对你有帮助。

例如,

    ImageView imageView = (ImageView) findViewById(R.id.imageview);
    Bitmap bitmap = loadBitmapAsset("my_nine_patch_image.9.png", this);
    NinePatchDrawable drawable = NinePatchBitmapFactory.createNinePatchDrawable(getResources(), bitmap);
    imageView.setBackground( drawable );

public static final Bitmap loadBitmapAsset(String fileName,Context context) {
    final AssetManager assetManager = context.getAssets();
    BufferedInputStream bis = null;
    try {
        bis = new BufferedInputStream(assetManager.open(fileName));
        return BitmapFactory.decodeStream(bis);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            bis.close();
        } catch (Exception e) {

        }
    }
    return null;
}

此示例案例中,my_nine_patch_image.9.png 位于 asset 目录下。

I create a tool to create NinePatchDrawable from (uncompiled) NinePatch bitmap.
See https://gist.github.com/knight9999/86bec38071a9e0a781ee .

The method
NinePatchDrawable createNinePatchDrawable(Resources res, Bitmap bitmap)
helps you.

For example,

    ImageView imageView = (ImageView) findViewById(R.id.imageview);
    Bitmap bitmap = loadBitmapAsset("my_nine_patch_image.9.png", this);
    NinePatchDrawable drawable = NinePatchBitmapFactory.createNinePatchDrawable(getResources(), bitmap);
    imageView.setBackground( drawable );

where

public static final Bitmap loadBitmapAsset(String fileName,Context context) {
    final AssetManager assetManager = context.getAssets();
    BufferedInputStream bis = null;
    try {
        bis = new BufferedInputStream(assetManager.open(fileName));
        return BitmapFactory.decodeStream(bis);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            bis.close();
        } catch (Exception e) {

        }
    }
    return null;
}

In this sample case, the my_nine_patch_image.9.png is under the assets directory.

云醉月微眠 2024-10-25 17:28:46

无需使用Android Binary Resource Compiler来准备编译好的9patch png,只需在android-sdk中使用aapt即可,命令行如下:
aapt.exe c -v -S /path/to/project -C /path/to/destination

No need to use Android Binary Resource Compiler to prepare compiled 9patch pngs, just using aapt in android-sdk is ok, the command line is like this:
aapt.exe c -v -S /path/to/project -C /path/to/destination

请恋爱 2024-10-25 17:28:46

所以您基本上想按需创建一个 NinePatchDrawable ,不是吗?我尝试了以下代码,也许它对您有用:

InputStream in = getResources().openRawResource(R.raw.test);
Drawable d = NinePatchDrawable.createFromStream(in, null);
System.out.println(d.getMinimumHeight() + ":" + d.getMinimumHeight());

我认为这应该有效。您只需更改第一行即可从网络获取 InputStream。根据文档,getNin​​ePatchChunk() 不适合由开发人员调用,并且将来可能会中断。

So you basically want to create a NinePatchDrawable on demand, don't you? I tried the following code, maybe it works for you:

InputStream in = getResources().openRawResource(R.raw.test);
Drawable d = NinePatchDrawable.createFromStream(in, null);
System.out.println(d.getMinimumHeight() + ":" + d.getMinimumHeight());

I think this should work. You just have to change the first line to get the InputStream from the web. getNinePatchChunk() is not intended to be called from developers according to the documentation, and might break in the future.

娇妻 2024-10-25 17:28:46

工作和测试 - 运行时 NINEPATCH 创建

这是我对 android Ninepatch Builder 的实现,您可以通过此类和下面的代码示例通过提供任何位图在运行时创建 NinePatch

public class NinePatchBuilder {
    int width,height;
    Bitmap bitmap;
    Resources resources;
    private ArrayList<Integer> xRegions=new ArrayList<Integer>();
    private ArrayList<Integer> yRegions=new ArrayList<Integer>();
    public NinePatchBuilder(Resources resources,Bitmap bitmap){
        width=bitmap.getWidth();
        height=bitmap.getHeight();
        this.bitmap=bitmap;
        this.resources=resources;
    }
    public NinePatchBuilder(int width, int height){
        this.width=width;
        this.height=height;
    }
    public NinePatchBuilder addXRegion(int x, int width){
        xRegions.add(x);
        xRegions.add(x+width);
        return this;
    }
    public NinePatchBuilder addXRegionPoints(int x1, int x2){
        xRegions.add(x1);
        xRegions.add(x2);
        return this;
    }
    public NinePatchBuilder addXRegion(float xPercent, float widthPercent){
        int xtmp=(int)(xPercent*this.width);
        xRegions.add(xtmp);
        xRegions.add(xtmp+(int)(widthPercent*this.width));
        return this;
    }
    public NinePatchBuilder addXRegionPoints(float x1Percent, float x2Percent){
        xRegions.add((int)(x1Percent*this.width));
        xRegions.add((int)(x2Percent*this.width));
        return this;
    }
    public NinePatchBuilder addXCenteredRegion(int width){
        int x=(int)((this.width-width)/2);
        xRegions.add(x);
        xRegions.add(x+width);
        return this;
    }
    public NinePatchBuilder addXCenteredRegion(float widthPercent){
        int width=(int)(widthPercent*this.width);
        int x=(int)((this.width-width)/2);
        xRegions.add(x);
        xRegions.add(x+width);
        return this;
    }
    public NinePatchBuilder addYRegion(int y, int height){
        yRegions.add(y);
        yRegions.add(y+height);
        return this;
    }
    public NinePatchBuilder addYRegionPoints(int y1, int y2){
        yRegions.add(y1);
        yRegions.add(y2);
        return this;
    }
    public NinePatchBuilder addYRegion(float yPercent, float heightPercent){
        int ytmp=(int)(yPercent*this.height);
        yRegions.add(ytmp);
        yRegions.add(ytmp+(int)(heightPercent*this.height));
        return this;
    }
    public NinePatchBuilder addYRegionPoints(float y1Percent, float y2Percent){
        yRegions.add((int)(y1Percent*this.height));
        yRegions.add((int)(y2Percent*this.height));
        return this;
    }
    public NinePatchBuilder addYCenteredRegion(int height){
        int y=(int)((this.height-height)/2);
        yRegions.add(y);
        yRegions.add(y+height);
        return this;
    }
    public NinePatchBuilder addYCenteredRegion(float heightPercent){
        int height=(int)(heightPercent*this.height);
        int y=(int)((this.height-height)/2);
        yRegions.add(y);
        yRegions.add(y+height);
        return this;
    }
    public byte[] buildChunk(){
        if(xRegions.size()==0){
            xRegions.add(0);
            xRegions.add(width);
        }
        if(yRegions.size()==0){
            yRegions.add(0);
            yRegions.add(height);
        }
        /* example code from a anwser above
        // The 9 patch segment is not a solid color.
        private static final int NO_COLOR = 0x00000001;
        ByteBuffer buffer = ByteBuffer.allocate(56).order(ByteOrder.nativeOrder());
        //was translated
        buffer.put((byte)0x01);
        //divx size
        buffer.put((byte)0x02);
        //divy size
        buffer.put((byte)0x02);
        //color size
        buffer.put(( byte)0x02);

        //skip
        buffer.putInt(0);
        buffer.putInt(0);

        //padding
        buffer.putInt(0);
        buffer.putInt(0);
        buffer.putInt(0);
        buffer.putInt(0);

        //skip 4 bytes
        buffer.putInt(0);

        buffer.putInt(left);
        buffer.putInt(right);
        buffer.putInt(top);
        buffer.putInt(bottom);
        buffer.putInt(NO_COLOR);
        buffer.putInt(NO_COLOR);

        return buffer;*/
        int NO_COLOR = 1;//0x00000001;
        int COLOR_SIZE=9;//could change, may be 2 or 6 or 15 - but has no effect on output 
        int arraySize=1+2+4+1+xRegions.size()+yRegions.size()+COLOR_SIZE;
        ByteBuffer byteBuffer=ByteBuffer.allocate(arraySize * 4).order(ByteOrder.nativeOrder());
        byteBuffer.put((byte) 1);//was translated
        byteBuffer.put((byte) xRegions.size());//divisions x
        byteBuffer.put((byte) yRegions.size());//divisions y
        byteBuffer.put((byte) COLOR_SIZE);//color size

        //skip
        byteBuffer.putInt(0);
        byteBuffer.putInt(0);

        //padding -- always 0 -- left right top bottom
        byteBuffer.putInt(0);
        byteBuffer.putInt(0);
        byteBuffer.putInt(0);
        byteBuffer.putInt(0);

        //skip
        byteBuffer.putInt(0);

        for(int rx:xRegions)
            byteBuffer.putInt(rx); // regions left right left right ...
        for(int ry:yRegions)
            byteBuffer.putInt(ry);// regions top bottom top bottom ...

        for(int i=0;i<COLOR_SIZE;i++)
            byteBuffer.putInt(NO_COLOR);

        return byteBuffer.array();
    }
    public NinePatch buildNinePatch(){
        byte[] chunk=buildChunk();
        if(bitmap!=null)
            return new NinePatch(bitmap,chunk,null);
        return null;
    }
    public NinePatchDrawable build(){
        NinePatch ninePatch=buildNinePatch();
        if(ninePatch!=null)
            return new NinePatchDrawable(resources, ninePatch);
        return null;
    }
}

。 现在我们可以使用 ninepatch 构建器来创建 NinePatch 或 NinePatchDrawable 或创建 NinePatch Chunk。

示例:

NinePatchBuilder builder=new NinePatchBuilder(getResources(), bitmap);
NinePatchDrawable drawable=builder.addXCenteredRegion(2).addYCenteredRegion(2).build();

//or add multiple patches

NinePatchBuilder builder=new NinePatchBuilder(getResources(), bitmap);
builder.addXRegion(30,2).addXRegion(50,1).addYRegion(20,4);
byte[] chunk=builder.buildChunk();
NinePatch ninepatch=builder.buildNinePatch();
NinePatchDrawable drawable=builder.build();

//Here if you don't want ninepatch and only want chunk use
NinePatchBuilder builder=new NinePatchBuilder(width, height);
byte[] chunk=builder.addXCenteredRegion(1).addYCenteredRegion(1).buildChunk();

只需将 NinePatchBuilder 类代码复制粘贴到 java 文件中,并使用示例在应用程序运行时以任何分辨率动态创建 NinePatch。

WORKING AND TESTED - RUNTIME NINEPATCH CREATION

This is my implementation of android Ninepatch Builder, you can create NinePatches on Runtime through this class and code examples below by supplying any Bitmap

public class NinePatchBuilder {
    int width,height;
    Bitmap bitmap;
    Resources resources;
    private ArrayList<Integer> xRegions=new ArrayList<Integer>();
    private ArrayList<Integer> yRegions=new ArrayList<Integer>();
    public NinePatchBuilder(Resources resources,Bitmap bitmap){
        width=bitmap.getWidth();
        height=bitmap.getHeight();
        this.bitmap=bitmap;
        this.resources=resources;
    }
    public NinePatchBuilder(int width, int height){
        this.width=width;
        this.height=height;
    }
    public NinePatchBuilder addXRegion(int x, int width){
        xRegions.add(x);
        xRegions.add(x+width);
        return this;
    }
    public NinePatchBuilder addXRegionPoints(int x1, int x2){
        xRegions.add(x1);
        xRegions.add(x2);
        return this;
    }
    public NinePatchBuilder addXRegion(float xPercent, float widthPercent){
        int xtmp=(int)(xPercent*this.width);
        xRegions.add(xtmp);
        xRegions.add(xtmp+(int)(widthPercent*this.width));
        return this;
    }
    public NinePatchBuilder addXRegionPoints(float x1Percent, float x2Percent){
        xRegions.add((int)(x1Percent*this.width));
        xRegions.add((int)(x2Percent*this.width));
        return this;
    }
    public NinePatchBuilder addXCenteredRegion(int width){
        int x=(int)((this.width-width)/2);
        xRegions.add(x);
        xRegions.add(x+width);
        return this;
    }
    public NinePatchBuilder addXCenteredRegion(float widthPercent){
        int width=(int)(widthPercent*this.width);
        int x=(int)((this.width-width)/2);
        xRegions.add(x);
        xRegions.add(x+width);
        return this;
    }
    public NinePatchBuilder addYRegion(int y, int height){
        yRegions.add(y);
        yRegions.add(y+height);
        return this;
    }
    public NinePatchBuilder addYRegionPoints(int y1, int y2){
        yRegions.add(y1);
        yRegions.add(y2);
        return this;
    }
    public NinePatchBuilder addYRegion(float yPercent, float heightPercent){
        int ytmp=(int)(yPercent*this.height);
        yRegions.add(ytmp);
        yRegions.add(ytmp+(int)(heightPercent*this.height));
        return this;
    }
    public NinePatchBuilder addYRegionPoints(float y1Percent, float y2Percent){
        yRegions.add((int)(y1Percent*this.height));
        yRegions.add((int)(y2Percent*this.height));
        return this;
    }
    public NinePatchBuilder addYCenteredRegion(int height){
        int y=(int)((this.height-height)/2);
        yRegions.add(y);
        yRegions.add(y+height);
        return this;
    }
    public NinePatchBuilder addYCenteredRegion(float heightPercent){
        int height=(int)(heightPercent*this.height);
        int y=(int)((this.height-height)/2);
        yRegions.add(y);
        yRegions.add(y+height);
        return this;
    }
    public byte[] buildChunk(){
        if(xRegions.size()==0){
            xRegions.add(0);
            xRegions.add(width);
        }
        if(yRegions.size()==0){
            yRegions.add(0);
            yRegions.add(height);
        }
        /* example code from a anwser above
        // The 9 patch segment is not a solid color.
        private static final int NO_COLOR = 0x00000001;
        ByteBuffer buffer = ByteBuffer.allocate(56).order(ByteOrder.nativeOrder());
        //was translated
        buffer.put((byte)0x01);
        //divx size
        buffer.put((byte)0x02);
        //divy size
        buffer.put((byte)0x02);
        //color size
        buffer.put(( byte)0x02);

        //skip
        buffer.putInt(0);
        buffer.putInt(0);

        //padding
        buffer.putInt(0);
        buffer.putInt(0);
        buffer.putInt(0);
        buffer.putInt(0);

        //skip 4 bytes
        buffer.putInt(0);

        buffer.putInt(left);
        buffer.putInt(right);
        buffer.putInt(top);
        buffer.putInt(bottom);
        buffer.putInt(NO_COLOR);
        buffer.putInt(NO_COLOR);

        return buffer;*/
        int NO_COLOR = 1;//0x00000001;
        int COLOR_SIZE=9;//could change, may be 2 or 6 or 15 - but has no effect on output 
        int arraySize=1+2+4+1+xRegions.size()+yRegions.size()+COLOR_SIZE;
        ByteBuffer byteBuffer=ByteBuffer.allocate(arraySize * 4).order(ByteOrder.nativeOrder());
        byteBuffer.put((byte) 1);//was translated
        byteBuffer.put((byte) xRegions.size());//divisions x
        byteBuffer.put((byte) yRegions.size());//divisions y
        byteBuffer.put((byte) COLOR_SIZE);//color size

        //skip
        byteBuffer.putInt(0);
        byteBuffer.putInt(0);

        //padding -- always 0 -- left right top bottom
        byteBuffer.putInt(0);
        byteBuffer.putInt(0);
        byteBuffer.putInt(0);
        byteBuffer.putInt(0);

        //skip
        byteBuffer.putInt(0);

        for(int rx:xRegions)
            byteBuffer.putInt(rx); // regions left right left right ...
        for(int ry:yRegions)
            byteBuffer.putInt(ry);// regions top bottom top bottom ...

        for(int i=0;i<COLOR_SIZE;i++)
            byteBuffer.putInt(NO_COLOR);

        return byteBuffer.array();
    }
    public NinePatch buildNinePatch(){
        byte[] chunk=buildChunk();
        if(bitmap!=null)
            return new NinePatch(bitmap,chunk,null);
        return null;
    }
    public NinePatchDrawable build(){
        NinePatch ninePatch=buildNinePatch();
        if(ninePatch!=null)
            return new NinePatchDrawable(resources, ninePatch);
        return null;
    }
}

Now we can use ninepatch builder to create NinePatch or NinePatchDrawable or for creating NinePatch Chunk.

Example:

NinePatchBuilder builder=new NinePatchBuilder(getResources(), bitmap);
NinePatchDrawable drawable=builder.addXCenteredRegion(2).addYCenteredRegion(2).build();

//or add multiple patches

NinePatchBuilder builder=new NinePatchBuilder(getResources(), bitmap);
builder.addXRegion(30,2).addXRegion(50,1).addYRegion(20,4);
byte[] chunk=builder.buildChunk();
NinePatch ninepatch=builder.buildNinePatch();
NinePatchDrawable drawable=builder.build();

//Here if you don't want ninepatch and only want chunk use
NinePatchBuilder builder=new NinePatchBuilder(width, height);
byte[] chunk=builder.addXCenteredRegion(1).addYCenteredRegion(1).buildChunk();

Just copy paste the NinePatchBuilder class code in a java file and use the examples to create NinePatch on the fly during your app runtime, with any resolution.

叹倦 2024-10-25 17:28:46

Bitmap 类提供了一个方法来执行此操作 yourbitmap.getNin​​ePatchChunk()。我从未使用过它,但似乎这就是您所寻找的。

The Bitmap class provides a method to do this yourbitmap.getNinePatchChunk(). I've never used it but it seems like thats what your looking for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文