I am creating a compound custom control. The control consists of a single element across the bottom and an unknown number of elements across the top. The background for each of these elements is a StateListDrawable defining the NinePatchDrawables to use for each state of that element.
As the individual top elements change their width to suit their content, the region of the bottom element directly below needs to also change width to suit. The top elements may also have their positions shifted left or right.
The images above and below are just quick mock-ups to convey the layout and behavior I need to achieve. I am not responsible for designing the actual background images to be used, but they will not be a uniform flat grey.
I managed to solve the first part of this re-sizing problem by:
onBoundChange()
.onDraw()
.This solution raises a number of problems though:
What I really need to achieve is:
Unfortunately as we know, you can't really play with the data Chunk. It's generated at compile time from the source image to create the NinePatch binary.
One of the better answers on this sort of topic can be found here. Based on this, a possible compromise solution might be:
getNinePatchChunk()
on the relevant dummy NinePatch compiled resource.NinePatch(Bitmap bitmap, byte[] chunk, String srcName)
.This seems like it would be a bit of a clunky way of doing things. Is there a better, more efficient way of going about this to achieve all the required goals?
Note: There are likely to be many instances of this custom control in a scroll view, when used in an app, so nested layouts need to be kept to a minimum.
I have finally come up with a way to avoid using a blank dummy NinePatch source as necessary my compromise solution above.
Based on this excellent solution to a similar problem, I have written a utility method to extract the padding info from a NinePatch resource. Using this, I can extract the necessary padding from the adjacent NinePatch regions, and apply them to my new slice. Hope this is helpful to others.
public static Rect getNinePatchPadding(Context context, int drawableId) {
Rect mPadding = new Rect();
Bitmap bm = BitmapFactory.decodeResource(context.getResources(), drawableId);
final byte[] chunk = bm.getNinePatchChunk();
if (!NinePatch.isNinePatchChunk(chunk)) return null;
ByteBuffer byteBuffer = ByteBuffer.wrap(chunk).order(ByteOrder.nativeOrder());
// Skip to padding
for (int i = 0; i < 12; i++) {
byteBuffer.get();
}
mPadding.left = byteBuffer.getInt();
mPadding.top = byteBuffer.getInt();
mPadding.right = byteBuffer.getInt();
mPadding.bottom = byteBuffer.getInt();
return mPadding;
}