Create simple 9 patch image that keeps logo in centre - android

I am trying to create a simple 9-patch image that keeps the image in the centre.
The logo I am using is similar to this:
The stretchable regions would of course be the sides and the top. The static region would the be the logo itself.
The tool I am using is the following:
https://romannurik.github.io/AndroidAssetStudio/nine-patches.html#&sourceDensity=320&name=example
Unfortunately, no matter how much I try I just can't seem to get this right.
I can easily make the logo stay on the top right, but not in the centre.
How do I get it so the logo stays in the centre?
Can someone show me how to achieve my desired behaviour. A screenshot will be ideal!

It turns out it was not possible using that tool as you can only place 2 stretchable regions.
Instead I used the tool provided by the android sdk located at:
path-to-android-sdk/tools/lib/draw9patch.jar
The above tool allows you to state multiple stretchable regions.
You need 4 to achieve the centre behabiour.
One on either side of the top edge and one on either side of the left edge.

Related

Creating & Using 9-patch images in Android

I recently heard about 9-patch images. I know its 9 tiled and is stretchable. I'd like to know more about it.
How can I create a 9-patch image?
Is there any tool? Can I create it from AndroidSDK or code?
Main Advantages of 9-patch over regular png?
(is it stretchable dynamically/ automatically according to screen?)
The SDK and Android Studio both ship with the "Draw 9-patch" tool ("draw9patch" in the SDK tools folder) which is a simple editor. Here is a nicer one which is also open source. It has a simple but clever default image.
The official documentation has improved over the years. In summary, nine patch images' most important advantage is that they can specify (non-contiguous) areas to scale:
A NinePatch graphic is a standard PNG image that includes an extra
1-pixel border. It must be saved with the 9.png extension in the
res/drawable/ directory of your project.
Use the border 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. The relative size of
the stretchable sections stays the same, so the largest section always
remains the largest.
You can also define an optional drawable section of the image
(effectively, the padding lines) by drawing a line on the right and a
line on the bottom. If a View object sets the NinePatch graphic as its
background and then specifies the view's text, it stretches itself so
that all the text occupies only the area designated by the right and
bottom lines (if included). If the padding lines aren't included,
Android uses the left and top lines to define this drawable area.
But the docs lack good examples. This tutorial has some great examples at the end that answer the second part of your question, explaining how the scaling works - not just for buttons - but also frames, and it has a complete example project that you can download and play with.
Most of the examples talk about creating a 9-patch image, but implementation details are usually left at a high level.
Nick's post above - with the good 9-patch tutorial that provides a working project download file , saved the day.
Here are the main implementation details that worked for me (once you have a 9-patch image ready to go):
Reference the drawable with the name but don't include .9.png (auto-complete in eclipse will take care of this)
Make sure you only have 1 image under the main /drawable folder (not a version for each dpi folder)
The image must be specified using :background, not :src (this got me stuck for a while)
android:background="#drawable/splash_logo"
Make sure the image and layout that contains it are using:
android:layout_width="fill_parent"
android:layout_height="fill_parent"
How can I create a 9-patch image? Is there any tool? Can I create it from AndroidSDK or code?
When you search a major search engine for android 9-patch tool, the very first hit is for the Android developer documentation page on the draw9patch tool.
Main Advantages of 9-patch over regular png? (is it stretchable dynamically/ automatically according to screen?)
The Android developer documentation contains other pages that describe nine-patch PNG files. This documentation includes passages like:
A NinePatchDrawable graphic is a stretchable bitmap image, which Android will automatically resize to accommodate the contents of the View in which you have placed it as the background. An example use of a NinePatch is the backgrounds used by standard Android buttons — buttons must stretch to accommodate strings of various lengths.
With 9-patch image you can choose which part of your image may be stretched.
It must be png image and name must end with .9.png (something.9.png)
http://developer.android.com/tools/help/draw9patch.html
Simple tool for all densities:
http://android-ui-utils.googlecode.com/hg/asset-studio/dist/nine-patches.html
1.What are NinePatch images?
NinePatch images are PNG images that mark the parts of an image that can be stretched. They have an extension like image_name.9.png.
2.Where they are stored in android project ?
res/drawable/image_name.9.png
3.How to create NinePatch image for your anndroid app ?
Android SDK includes a WYSIWIG draw9patch.jar tool inside your Android SDK /tools folder.
Main Advantages of 9-patch over regular png
Actually 9 Patch images are stretchable, repeatable images reduced to their smallest size.the image won't stretch and loose proportions in different screen sizes. One more and biggest advantage is memory.
Same small size memory can be reused for different screen size devices. Well-designed 9-patch images are less error-prone and have high re-usability .
https://developer.android.com/studio/write/draw9patch.html
This is good tool:
Click here.
9 Patch images are stretchable, repeatable images reduced to their smallest size. The simplest example would be if you were to take a rounded div and slice it up into 9 squares like you would a tic-tac-toe board. The four corners wouldn't change sizes at all but would be static while the other 5 pieces would be stretched or repeated to allow the whole image to scale appropriately.
With that explanation and the advent of CSS3 you might think that there is no reason to use 9 patch images but the name '9 patch' is a misnomer. The images can be sliced up into even smaller pieces.
9 Patch images contain an index of which piece is what by adding a 1px border to the image. The colors in the border determine if a piece is static (doesn't scale), it stretches, or it repeats.
Google Slideshow: https://docs.google.com/present/view?id=dc7ghz8w_34f8338rcg
See also the Android developer info about 9-patch images: http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
Step 1, Since you are not familiar yet, prepare a xxxhdpi png big image to play around first.
Step 2, That image desired expandable field must shorter (by removing redundant/repeated color part) as possible since 9-patch no such thing "reduce", but "expand" the image.
I personally use the ImageMagick command line tool to convert it, e.g.:
convert -trim 'my_image.png' png32:my_image_trim.png #trim extra transparent surrounded image
rm lala*; convert my_image_trim.png -crop 310 +repage +adjoin png32:lala%02d.png #cut redundant/repeat center part
convert +append lala02.png lala05.png png32:out_right.png #append left/right images side by side
convert -resize 144x144\! out_right.png png32:my_image.png #resize to the desired dpi
There is one pitfall when convert: I must prefix with png32, or else will get black 9-patch image, see this thread.
Step 3, Copy image to Android Studio drawable, then right-click and choose menu item "Create 9-Patch file...". A .9.png new image will be generated with the same image name. Now can just delete the original image. Careful when playing around with refactor to rename for backup since it will rename the XML image id too, and make you wonder why the 9-patch image not working since XML still referring non-9-patch image.
Step 4, Left and top 2 black lines form an expandable rectangular area, while right and bottom 2 black lines form a text rectangular area.
Your image size will grow on your declared expandable area as text growing. While the text area means text only allow in that area.
You don't have to draw the black dot/lines from scratch for simple usage, 4 black lines already existed behind the top, left, bottom, right on that image if your 9-Patch image generated by Android Studio. "Zoom in" to bigger if you can't see to drag that lines.
The original position of 2 black lines, vertical and horizontal, both declare an expandable area:
The original position of left vertical line is between upper left to bottom left
The original position of top horizontal line is between upper left to top right.
The original position of 2 black lines, vertical and horizontal, both declare a text area:
The original position of right vertical line is between upper right
to bottom right.
The original position of bottom horizontal line is
between bottom left to bottom right.
Above is the original position of black lines before you start to drag to narrow down the length, to adjust the start position and end position of that lines.
Both expandable and text areas can be different depends on your needs. But normally expandable area should equal OR less than text area, a classic example will be chat bubble image:
The image above has equal top and bottom black lines width but right black line is higher than left line, which also means that text consistently stay up to half of bottom curve in either minimum size or expanded size. And it only expand in body of text area.
Now you will know the two benefits of 9-Patch: the bottom and right line together form a text area which perfectly ensures text never overflow to outside of image curve ! And also defined which portion of text area responsible to expand the image as text growing, while keep the curve without scaling.
Hover the line will able to see the x,y positions in pixels, it help to measures both lines are equal or less in position.
You should remember the position of line when dragging, since left line can drag to right side, and the right line can drag to left side, and you may get lost of which line is expandable line and which line is text line.
There are 2 important checkboxes you should tick, i.e. "Show patches" and "Show bad patches" checkboxes.
In "Show bad patches" checkbox, if you drawing the expandable area but covering the curved line of your image instead of a straight line, then it will mark that area as red to warn you. You can narrow your line to dismiss that red warning, or just ignore it. Keep in mind that, the red warning may misleading which may actually be caused by the opposite line, in that case, you need to narrow the opposite line to dismiss that red warning.
Step 5, In xml, you can refer to that image as TextView background like below, use wrap_content to make it expandable:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/your_9_patch_image_name_excluded_.9"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<2nd TextView />
</LinearLayout>
When first time playing around with it, ensures no padding on textview or fancy parent layout, or else you may wonder why not working as expected.
Button background example:
<Button
android:id="#+id/btn2"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="#drawable/your_9_patch_image_name_excluded_.9"
android:layout_gravity="center"
/>

Is it possible to make a 9-patch drawable for a callout graphic?

I'm trying to make a callout graphic in Android. I'm not married to the idea of using a 9-patch-drawable, but I think it's the right way to go. I'm essentially trying to make a button with a little nub at the bottom. I'd like the nub to be centered regardless of the size of the content. Here are some example graphics showing what look I'm going for:
Is there a way to keep the bottom little nub centered using a 9-patch drawable?
Is there a way to keep the bottom little nub centered using a 9-patch drawable?
Yes, absolutely. As a matter of fact, a 9-patch is definitely the right way to go for this.
Just make your 9-patch have two stretchable regions: one to the left on the nub and one to the right. You'll want to make sure both regions are equally 'large'. In other words: the two horizontal black lines that define the horizontally stretchable regions should have equal length - that will make the nub stay in the horizontal center.
Here's are two examples of images that are part of the mapview-balloons library:

Android: how to use the 9patch creator?

I am trying to create a stretchable scroll handle for my app.
The first image is the scrollhandle.9.png that I include in my app's resources.
The second image shows what this 9patch image looks like when used in my app.
Any advice on how to accomplish a stretchable scroll handle?
Edit: With help from posters, I was able to get an image that works. I added it below to help those who may find this in the future.
The area covered by the top and the left black line(dots) will be used while scaling your image. This area will be highlighted to you when you click the "show patch" option. You can see how the image scales by using the "Patch scale" option given in the draw9patch tool.
The area covered by the right and bottom lines(dots) will hold the content for the background.
Eg: You can define boundaries for the text inside 9 patch image for editor background. For your case you don't need right and bottom lines.
So for your case place two dots at the top corner and two dots at the left corner. Make sure patches doesn't fall in the arrow image of the scroll(if they do fall your arrow image will also get stretched) . Try putting the dots only in the left and top lines till you get the desired preview with "Patch scale" option.
If you use only one dot (instead of four) at the top and bottom left, and one at image top center, it should stretch the way you want it to.

Phonegap - Android Splash Screen - Centre Logo

Can anybody advise me on how to setup a splash screen to work cross resolution?
I have tried re-sizing a png file to different dimensions and placing the image in the ldpi,mdpi,hdpi folders, but the image still looks stretched/squashed depending on the device.
Is there a way to place a logo centre of the screen with a white background, i'm happy to use one size of logo even as long as it sits in the middle and looks ok¬?
Does anyone have any advice?
Cheers
Paul
Have you heard of/considered using a 9 patch version of the logo? A nine patch image allows you to define areas of an image which can be stretched. If you create your logo png file with a white background and then set the white area as stretchable it will then fill your container nicely but the logo part of the image will not distort at all.
In your android-sdk directory, under the tools subdirectory, execute a tool called draw9patch
./draw9patch
Drag your image in there. Use the left view for drawing pixels on the top and left sides. Use the right view for inspecting how your image will stretch on different devices.
OK, the answer has EVERYTHING to do with the stretchy areas of your 9patch image. I found the answer by pinging the github question. A user sent me to another discussion where someone had cracked it.
The main issue is that most 9patch tutorials explain how to stretch buttons, but none detail how to center an image.
Look for the green/blue/red image a little more than half way through the discussion.
http://community.phonegap.com/nitobi/topics/stretched_9_patch_splash_screens_android
The key for me was to look at the edges. It's really hard to see (for me at least), but you can barely make out the black marks along the edge that define the stretchy areas. top has 2 small areas (on the green), left has 2 small (on the green), bottom has one long (on the blue), right has one long (on the blue).
Consequently, I find this one image (as hard as it is to see the lines) a better instruction on how 9patch works than all of the tutorials I've watched.

Android : Alignment bug in making/showing 9patch image

NinePatch:
Screenshot:
Layout XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#ffffff">
<LinearLayout
android:id="#+id/edit_tray"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<View
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/trash"/>
</LinearLayout>
</RelativeLayout>
Desired Results:
The "edit_tray" represents a UI element that will be toggleable. When edit mode is off, the "edit_tray" (and therefore the trash can icon) are "gone". When edit mode is on the "edit_tray" is visible and overlaid over the ScrollView contents.
There are two elements to the trash can icon: The icon itself and the linear gradient behind it. The NinePatch image contains three stretchable areas and one static area to accommodate these elements. The trash can icon in the middle of the graphic is static and should appear directly in the horizontal center and on the bottom of the screen. The gradient should stretch across the bottom of the screen from one side to the other.
The Bug?
The NinePatch image contains only one pixel of stretchable area on either side of the image horizontally. The effect of which should be that the trash can icon appears directly in the center (1 pixel on left side == 1 pixel on right side). However, as you can see in the screenshot above that is not the case. Note: this screenshot was taken from my test phone, a T-Mobile G2. The same effect can be seen in the emulator. However, in the draw9patch preview and the eclipse Graphical Layout view the image is perfectly distributed.
I've tried several different methods to try to find out where the bug is and to try to fix it or work around it. Including: using ImageViews instead of Views (same effect), using android:scaleType="fitXY" (same issue), checking at runtime that the width of the screen and the width of the "edit_tray" are the same (they are), using two different images for gradient (as edit_tray background) and icon (as ImageView src) (create another problem where the two images were not overlayed on each other. Fixed by setting an absolute height on both), etc.
The Answer, the Workaround, and the Real Question
I did some testing using some simple NinePatch images with up to six stretchable areas per side. I noticed there were some issues displaying them in at least one of the testing cases (phone, emulator, draw9patch, Graphical Layout in eclipse).
I decided to try to expand the image horizontally so that there was more of the linear gradient showing on the edges of the trash can icon. I made the image 128x64 (previously 64x64). I made more of the edges part of the stretchable part to try to curb any bad math (?) that was happening to the image. Draw9patch reported bad sections so I put it back to just the two pixels, one on either side. It worked! The icon is directly in the center of the screen now! I don't know why, but without changing the actual stretchable portion of the image, only changing the width of the image to 128, it works now.
I tried resizing the image back down to around 100px wide to remove some of the redundant pixels and the error came back! Not only did it come back, but the icon was placed at exactly the same spot offset from the center of the screen. I can't figure out why this would happen this way.
Anyone have any ideas? Is this a bug?
I currently have this working given the workarounds I described above, but if anyone has any suggestions I'm listening.
Make your 9 Patch image with using 4 points as I have done in this..and it will work.
Tips for Creating 9 Patch Image.(not a designer,telling you my funda)
Put points on Left and Top
If you have some text or image in between ..then put point on left
and right of image and top and bottom of that image or text.
Always see the no of space left and no of points on both sides(left-right and top-bottom) are equal.
Always check once the preview or right side before using check in 2x
to 6x
From my experience with the draw 9-patch tool there is an automatic 1px offset on each side of the image. Given this information if you were using just this one pixel offset your image was actually not being stretch the way you would imagine.
This can be seen by the fact that when you used a 2px offset it worked perfect.
Also the 9-patch images have a tendency of showing up in eclipse exactly how you would think... but then appearing different on the phone/emulator.
Learning the 9-patch tool is def a great thing as it allows greater customization. Another tip, if you want to do something like replace any android 9-patch with your own alterations - then just copy the 9patch that exists in the SDK and alter it. For some reason 9patch images in the SDK have weird offsets. Doing this will guarantee you don't get weird responses from your 9-patches. An example of this - I outline an editText in red when bad input is given.
The SDK images can be found in SDK->platforms->[plateform-you-want]->data->res-drawable-[you-choice]
You can also look at the SDK 9-patch images to help understand how the 9-patch-tool works.
Hope this give a little more insight.
Here are some good links:
http://developer.android.com/guide/developing/tools/draw9patch.html
http://android10.org/index.php/articlesother/279-draw-9-patch-tutorial
http://jaanus.com/post/7878186745/how-does-androids-nine-patch-tool-work-from-a
Maybe it's bug in nine-patch drawing, or just error resulting from rounding.
However, I don't like your approach of drawing this icon. You try to position your screen element using something that is not designed for this task.
You should draw it other way: create some container view (FrameLayout) with gradiend background. Then on top of that position ImageView with trash can. Neither of these 2 images need to be nine-patch, gradiend would fill entire view, trash can would be drawn without scaling.
Although there's overdraw in area of trash view, CPU time is not wasted in nine-patch areas computations.
You would use layout system for exact positioning of your trash icon. Certainly you would get expected result, since UI layouts are well tuned, and made for purpose of positioning screen elements. Nine-patch images are used for other purpose (where pixels shifted here or there a bit should not matter).
As #jjNford said - it's bad practice to work with images in this way.
For this task the best solution is to create "trash" icon with transparent background, and create shape drawable with gradient. So, you can remove unnecessary LinearLayout and use only ImageView:
<ImageView
android:id="#+id/edit_tray"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:src="#drawable/trash"
android:background="#drawable/gradient_background"/>
Docs for shape drawable.
EDIT
Just check your image - it starches fine on SE Xperia 2.3.3

Categories

Resources