Building a 9 patch drawable at runtime

白昼怎懂夜的黑 提交于 2019-11-28 06:59:18
Neil Townsend

Putting together all I've spotted so far, and honing it a bit:

  • There doesn't seem to be a difference in the Res_png_9patch structure (which the byte chunk goes into) between android versions (see http://code.metager.de/source/xref/android), so that doesn't look like the cause.

  • Other answers about nine patch drawables suggest that each region (especially stretchable ones) should be at least 2x2 pixels (if not 3x3), but outside of that smaller is better.

  • However, the way some of the byte chunk is allocated looks like it could be updated. Try setting the 4th byte to 9 (the number of patches, I think), adding 7 more NO_COLORs to the the end and moving its size up to 56 + (7 x 4) = 84 bytes

It's working for me after I updated the code. I think the color size made it unhappy for some reason(Based on the comments in the android source code each patch has a color hint, setting fewer than the number of sections in this case 9 appears to cause problems). I haven't tested with your image yet.

public static NinePatch createFixedNinePatch(Resources res, Bitmap bitmap, int top, int left, int bottom, int right, String srcName){
    ByteBuffer buffer = getByteBufferFixed(top, left, bottom, right);
    NinePatch patch = new NinePatch(bitmap, buffer.array(), srcName);
    return patch;
}

public static ByteBuffer getByteBufferFixed(int top, int left, int bottom, int right) {
    //Docs check the NinePatchChunkFile
    ByteBuffer buffer = ByteBuffer.allocate(84).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)0x09);

    //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);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    buffer.putInt(NO_COLOR);
    return buffer;
}
Aux

Looks like working with 9patches is described in depth on SO already - Create a NinePatch/NinePatchDrawable in runtime

Not really an answer to the question, but a useful workaround...

I've always found working with 9-patch files at runtime to be hairy. I have been successfully able to use FrameLayouts and automatic resizing of text to accomplish my desired effects. If your app will just be using this 9-patch, and not specifically allowing the user to download it as an image (an android 9-patch image generator, so to speak), I would advise you to look into that.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!