While I was working on my Android App I
found 9-patch (aka 9.png) to be confusing and poorly documented. After a little
while, I finally picked up on how it works and decided to throw together
something to help others figure it out. As Android devices
come in many shapes and sizes, often making it very difficult for developers to
design applications that look great on all the various screen sizes and
orientations. For addressing this challenge,9-patch can be indispensable. In this article, I will discuss
what the 9-patch graphics format is, how it works, and when to use it.
What is the 9-patch !!! |
Android supports 9-patch Stretchable Graphics for the
controlled scaling of images. 9-patch graphics uses .png transparency to do an advanced
form of 9-slice or scale9 that
have patches, or regions of the image, defined to scale and stretch in the
appropriate areas instead of scaling the entire image as one unit, which often
obscures the details of the graphic. Generally, the center patch is transparent
or solid, With parts of
the edges set to remain fixed, other edge parts set to stretch, and the corners
set to remain fixed.
Here’s a basic guide map:
As you can see, you have guides on each side of
your image. The TOP and LEFT guides are for scaling your image (i.e. 9-slice),
while the RIGHT and BOTTOM guides define the fill area.
The black guide lines are cut-off/removed from your
image – they won’t show in the app. Guides must only be one pixel wide,
so if you want a 48×48 button, your png
will actually be 50×50. Anything thicker than one pixel will remain part of
your image. (My examples have 4-pixel wide guides for better visibility.
They should really be only 1-pixel).
Your guides must be solid black (#000000). Even a
slight difference in color (#000001) or alpha will cause it to fail and stretch
normally. This failure won’t be obvious either*, it fails silently! Yes.
Really. Now you know.
Also you should keep in mind that
remaining area of the one-pixel outline must be completely transparent.
This includes the four corners of the image – those should always be clear.
This can be a bigger problem than you realize. For example, if you scale an
image in Photoshop it will add anti-aliased pixels which may include almost-invisible pixels
which will also cause it to fail*. If you must scale in Photoshop, use
the Nearest Neighbor setting in the Resample Image pull
down menu (at the bottom of the Image Size pop-up menu) to keep sharp edges on
your guides. This is actually a “fix” in the latest dev kit. Previously it
would manifest itself as all of your other images and
resources suddenly breaking, not the actually broken 9-patch image.
The TOP and LEFT guides are used to define the scalable portion of your
image – LEFT for scaling height, TOP for scaling width. Using a button image as
an example, this means the button can stretch horizontally and vertically
within the black portion and everything else, such as the corners, will remain
the same size. This allows you to have buttons that can scale to any size and
maintain a uniform look.
It’s important to note that 9-patch images don’t scale down – they only
scale up. So it’s best to start as small as possible.
Also, you can leave out portions in the middle of the scale line. So for
example, if you have a button with a sharp glossy edge across the middle, you
can leave out a few pixels in the middle of the LEFT guide. The center
horizontal axis of your image won’t scale, just the parts above and below it,
so your sharp gloss won’t get anti-aliased or fuzzy.
Fill area guides are optional and
provide a way define the area for stuff like your text label. Fill
determines how much room there is within your image to place text, or an icon,
or other things. 9-patch isn’t just for buttons; it works for background images
as well.
The above button & label
example is exaggerated simply to explain the idea of fill – the label isn’t
completely accurate. To be honest, I haven’t experienced how Android does
multi-line labels, but there’s a good explanation of how to do them on Stack Overflow. Usually,
a button label is usually a single row of text.
Finally, here’s a good demonstration of how scale
and fill guides can vary, such as a LinearLayout with a background image &
fully rounded sides:
Creating 9-patch Graphics
Let's give it a
try. I've created a really basic PNG file called bluenotstretchy.png. To create a NinePatch graphic from this PNG file using the
Draw 9-patch tool, perform the following steps:
1.
Launch Draw
9-patch.bat in your Android SDK /tools directory.
2.
Drag the PNG file into the
left-hand pane (or use File -> Open NinePatch…)
3.
Click the "Show Patches"
checkbox at the bottom of the left pane.
4.
Set your Patch Scale appropriately
(higher to see more obvious results).
5.
To set a horizontal patch guide,
click along the right edge of your graphic.
6.
To set a vertical patch guide,
click along the top edge of your graphic.
7.
View the results in the right
pane, and move patch guides until the graphic stretches the way you intend
it.
8.
If you need to delete a patch
guide, press Shift and click on the guide pixel (black).
9.
Save your graphic with the
extension .9.png (e.g., blue.9.png).
Loading 9-patch Graphic Resources from java file :
9-patch resources are simply another kind of Drawable
subclass called NinePatchDrawable. Most of the time, you'll need only the
resource ID of the image, to set as an attribute of View or layout.
Occasionally you might need to act on the resource programmetically.
To create a NinePatchDrawable object from a NinePatch
drawable resource, use the resource'sgetDrawable() method. If the drawable is a NinePatch, the getDrawable() method will return a NinePatchDrawable instead of a
generic BitmapDrawable object.
For example, to load a NinePatch drawable resource
called blue.9.png, you could use
the following code:
import
android.graphics.drawable.NinePatchDrawable;
…
NinePatchDrawable
myNinePatchDrawable = (NinePatchDrawable)
getResources().getDrawable(R.drawable.blue);
You can then use the NinePatchDrawable object much as you
would any BitmapDrawable.
Do post your doubts, queries or suggestions in
this blog.
Hey..Thanks a lot...Its really a great article. I always face trouble while running my app on different screen size devices. But finally I got solution here. Thanks a lot again.
ReplyDelete