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:
- Creating a custom class which extends Drawable.
- Passing the class an array of NinePatchDrawables defining various potential regions of the Bottom View (eg left_end, right_end, middle_below_control, middle_below_gap).
- Changing the bounds of each to match the relevant view above during the custom class'
onBoundChange()
. - Drawing my array of re-sized NinePatches to the Bottom View canvas in
onDraw()
. - Setting a combined padding for the Bottom View based on the padding of the NinePatches in the array.
This solution raises a number of problems though:
- You need StateListDrawables for each of the potential regions of the Bottom View.
- You need individual NinePatch images for each of the states in each of these StateListDrawables.
- You have to design an image for the Bottom View which is restricted to being very uniform across it's width.
- You need ear defenders and a thick skin to deal with all the shouting from the graphic designers.
What I really need to achieve is:
- Have a single StateListDrawable for the Bottom View.
- Extract the single image for each state and slice it up into the required sections.
- Create a new NinePatchDrawable for each slice, applying the data Chunk from the view above for width only. Not height.
- Then re-combine them as per my previous solution above.
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:
- For each of the top element types, have the graphic designers supply an additional blank dummy NinePatch source with the identical height and width dimensions, identical width padding and patch definitions, but with the height padding and patch definitions as they want for the bottom view.
- Use
getNinePatchChunk()
on the relevant dummy NinePatch compiled resource. - Combine the resulting data Chunk with the relevant Bottom View bitmap slice to create a new NinePatch using
NinePatch(Bitmap bitmap, byte[] chunk, String srcName)
. - Put up with dirty looks from the graphic designers, but at least they've stopped shouting.
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.