So i had to you a 9-path, for couple of month now i let our designer do the 9-path thing. If any of you think he bothered reading the docs. you are dead wrong , designer, what did you expect happy little guy with 0 tolerance for long writings…. i used the 9-pathces for button’s backgrounds and for dialogs background, but alas! in some cases i got very very strange results which i could not understand. I had to turn to the documentation to check what it says regarding 9-patches and what the lines on top, bottom right and left actually mean…
So the android documentation states, and i quote : “The border is used to define the stretchable and static areas of the image. You indicate a stretchable section by drawing one (or more) 1-pixel-wide black line(s) in the left and top part of the border (the other border pixels should be fully transparent or white). You can have as many stretchable sections as you want: their relative size stays the same, so the largest sections always remain the largest.” – meaning the top and left lines of a 9-patch are responsible for the stretching areas. not only that the same proportions of the stretch are saved so if you image is 10 px long, and you have two stretch area, one is 4 px long and one 2 px long relation of 1:2 will be kept while stretching it, meaning one part will always be double sized from the other.
However this does not always work properly, for example if you have an image with round corners that also got some extra image in the bottom like a pointed arrow that should always be kept in the middle, if you wont stick to two dots you might end up with the arrow not being in the middle….
Couple of tips regarding stretching and the image:
- make the image as small as you can , if the stretch area looks the same all over and you don’t have much padding to do, don’t make a wide image, a single dot can define the area to be stretched so and image can be even9-10 pixels wide and it’s enough.
- don’t use more stretchable are then you need you might get sometimes strange results especially if you use 3 nine-patch for a state drawable and they might be calculated differently in size.
- when doing horizontal stretching be careful, especially between dpi’s , when stretching gradient images
- if you use round corners images make sure, naturally, that the corners are OUT of the stretch area…
Now comes another question, ok, so the upper part is for stretching the width, the left part for stretching the height. what are the tight and bottom lines for ?
So again i’ll quote: “You can also define an optional drawable section of the image (effectively, the padding lines) by drawing a line on the right and bottom lines. If a View object sets the NinePatch as its background and then specifies the View’s text, it will stretch itself so that all the text fits inside only the area designated by the right and bottom lines (if included). If the padding lines are not included, Android uses the left and top lines to define this drawable area. ”
What does that mean ? first of all it’s optional, so if i don’t define it ? according to the Editor (9-patch Editor that comes with the SDK) it seems like the default is to catch the whole area as the drawable area, meaning 0 padding. the programmers thought different. if you don’t define the padding the default is to take the areas between the stretchable areas and make them your padding! for example take a look on the following image:here in this image we gave most of the height for stretching beside the corners, and only 3 pixels for the width, excluding anything related to the corners. We could have managed with only one pixel too.Now according to the 9-patch Editor if you’ll mark the ‘show content’ the red markings will mark the whole area, which is basically the right behavior for default. BUT if u’ll use this as a background for a button or a TextView you’ll discover reality is much different.the button is 17 pixels wide. we have marked 3 pixels 4 pixels from the left corner and 11 pixels from the right corner, so you will get padding the truth is the the stretchable area becomes also the text area meaning the ratio must be kept as so there will be 4/17 pixels from left and 11/17 pixels from right and stretching the image using the 3 pixels we chose. This is not very convenient. What’s more is that even when i personally used the padding lines for padding about 5 pixels from the bottom, for some reason i did not get the same padding for all the images, and since it was two left and right buttons for a tab switcher (meaning they were one next to the other and should have the same height and text padding) it was very visible, i double checked i have the exact same line size in the 9-patch, to no avail. So my Advise here is simple:
- don’t leave the padding for chance and if you do make sure your stretchable area lines covers also the area meant for writing content so the padding will be really only the area you don’t use, and make sure it’s symmetric so you wont have nasty surprises when you get to see you TextView and don’t understand why the text isn’t in the center…
- Do fill the whole padding line so there’s 0 padding for the 9-patch, define your padding in a style and apply it to your View, in my opinion, it’s safer and less time consuming than playing around with the 9-patch editor.
9-patches are Google’s choice for android’s saving on images size. it’s got it’s advantages (yes takes up less size, stretchable pretty easily…) and disadvantages (if you use gradient you can’t stretch it too much, for higher DPI you’ll need new 9-patch, problems with padding, need to work a bit to create them), but that’s what you have on android and if you want your app to be lightweight and scale well you need them! so i gave here some tips on how to do it safely at least for us, programmers and i suggest using them whenever and optimize your images, really, no need for image that you know stretches horizontally to be bigger then 10-20 pixels like you saw in the buttons example (17 pixels). Hope you’ll benefit from the post.