问题
I am successfully building a 9patch drawable at runtime on Android 3.0+ using the excellent gist provided by Brian Griffey (found here).
Essentially I load the raw (no patches) graphic file from the network and the filename contains the cap insets that I need to use in order to scale the image accordingly. I then use these values with the class found above and apply the image as a background to a variety of elements (such as TextView
, ImageButton
, Button
, ViewGroup
, etc).
This works perfectly as you can see here:
However, running the same code on Android 2.3.x yields the result:
I've looked through the source code used in Android to parse a 9patch image (here and here) but have found no method of getting this to work correctly. I've tried just about everything I could throw at it to no avail.
For the record, the 9patch consists of three columns on each axis, one fixed, one stretchable and one fixed.
Here's hoping someone else has solved this problem before.
Thanks in advance.
EDIT I am only interested in duplicating this behavior on Android 2.3 and above (I originally had 2.x).
EDIT #2 This gist describes exactly what I'm trying to do + Source image:
EDIT #3 The size of the image is 22px/58px (width/height) and the insets are 14/6/14/6 (top/left/bottom/right).
回答1:
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_COLOR
s to the the end and moving its size up to 56 + (7 x 4) = 84 bytes
回答2:
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;
}
回答3:
Looks like working with 9patches is described in depth on SO already - Create a NinePatch/NinePatchDrawable in runtime
回答4:
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.
来源:https://stackoverflow.com/questions/16509404/building-a-9-patch-drawable-at-runtime