I am sure when the Google team came up with the 9-patch image, they must have felt real smug. Engineers excitedly talking around coffee machines about the pure awesomeness of it’s capabilities must have been a common sight. And in all the excitement they conveniently forgot to write all about it and hoped that designers and developers would miraculously figure out how it worked and more importantly how it didn’t.
Fortunately days have improved and there is now some documentation available at http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch, but I might add that it is the bare minimum.
I have also seen numerous cases where the designers and developers have been at each others’ throats trying to figure out who is responsible for all the screwed up 9-patches. So here’s an attempt at spreading peace and bringing the two at the same page.
Where do I use a 9-patch?
There are many situations where in the backgrounds are same though the sizes of the View elements may vary in size. For example backgrounds of buttons whose size depend on the button text size. Backgrounds for ViewGroups whose size vary based on the content. In such situations, adding multiple backgrounds for each of the elements is pointless.
The image below shows how different backgrounds on the left can be replaced by a single, much smaller 9-patch image and yet achieve the same result.
Before we go all technical about 9-patch, here are some basics
- 9-patch image is a Stretchable Bitmap Image.
- It has a 1-pixel transparent border on which the stretchable and the static areas of the image are defined using black color.
- It has an extension .9.png. For example, image.9.png.
- As of now two things can be defined of the image, the SCALABLE Area and the FILL Area (can be also referred to as the padding of the image).
- TOP/LEFT borders are used to define the scalable areas while BOTTOM/RIGHT is used to specify the fill area.
- Multiple scalable areas can be specified for the image.
The image above shows all the Scalable and Fill areas. You might find it a little confusing in the beginning but by the time you are done with this, it will all make sense.
The 9-patch structure
This shows the basic structure of the 9-patch. You will observe that there are 9 divisions and hence the name 9-patch. The four corners remain static and do not scale in any direction. The center-left and center-right areas scale only along the Y-axis while the top-center and bottom-center stretch only along the X-axis. The center of the image stretches in both the X and Y directions.
Creating a 9-patch Image
Below are the steps to create a 9-patch image using Photoshop or any other image editing tool such as GIMP because I am sure most designers would be using one of them. Developers on the other hand wouldn’t. Click here if you are a developer and want to use the Draw 9-Patch tool.
1. Let us say that we want to make an image that is 48×48. So we start of with an image of the size 48×48.
2. Now we add a transparent border to this image. As a result the size would now be 50×50.
3. Next we use a pencil/pen tool with size 1 pixel, select the color as black and mark along the top and left borders to specify the area that we want to scale. You should end up with an image similar to the one shown above.
4. Finally specify the fill area by marking along the right and bottom borders.
Here are a couple of examples demonstrating how different scalable areas result in different types of scaling.
In the example below you will notice that, we have marked multiple patches on both left and top borders. As a result we now have 9 static areas, 12 partial stretchable areas and 4 complete stretchable areas. This helps us in cases where we don’t want certain parts of the images to be scaled. You can see how the red dot has remained uniform, no matter how it is scaled. In the previous case, the red dot was getting scaled along with the image size.
Fill areas or Padding
We now look into the area which the Android docs say is optional, though doesn’t clearly mention what the side effects would be. The Fill area can be specified by drawing black lines along the right and bottom borders. The content is restricted within the area specified by these lines. In the adjacent image, the area marked by the intersection of the left and right lines will be the content area of the View whose background is set with this 9-patch image.
The docs say that if these “optional” lines are not specified, then Android uses the top and left lines to define the fill area. Can you imagine how catastrophic the result would be in one of the example above? Well fortunately there is a way to deal with such cases but unfortunately it is not mentioned in the docs. You can see the “For the developers” section below for cases where the padding lines are not provided.
Points to Remember
Now that you know what 9-patch images are and how they are made, here are a few points you must keep in mind before you start.
- 9-patch images can scale up but not scale down. Scaling down results in visual artifacts.
- Always design for the smallest size possible. This will increase its re-usability.
- If the Fill Area is not specified, then Android uses the top and left lines to define it. This may lead to visual artifacts.
For the Designers
- The transparent border MUST be absolutely transparent and the border lines MUST be absolutely black ie #000000.
- While resizing 9-patch images, remove the border, re-size it and then add the border. If you use an image editor to create and resize 9-patch, then antialiasing can ruin your image.
- Android prefers that the ‘intersection zones’ are 1×1 pixel size for proper scaling. For bigger zones, the scaling could lead to visual artifacts.
For the Developers
- If the Fill Area is not specified, there maybe abnormal behavior. In such cases, always specify some padding. And if you don’t require padding then use “padding=0dp”.
- Put your 9-patch image in the /res/drawable folder to use for different densities and screen sizes and make sure they have “.9.png” extension.
- If you are using the same 9-patch for different densities, then be cautious. The static areas will appear different based on the density. Make sure you check them on real devices and then decide if you require separate images for separate densities.
- Do not use a 9-patch image that is bigger than your View.