I'm trying to create a 9-patch image that only stretches horizontally, and as you can see in the attached image, I drew only in the center top.
The second image in the preview (the middle one) shows what I think it's wrong. I just want to stretch the middle, so it makes no sense to me why it isn't displaying the right part of the image - the frill. The left part is OK, thought.
Any help is appreciated!
Edit: Added another image to show it with "show patches" and "show content" enabled:
The layout defines how much and in what direction an image gets stretched. A 9-patch can only define what parts of an image should be stretched and which parts not. You can basically exclude parts of the image from stretching. In your example the left and the right parts won't be horizontally stretched. They will, however, still be stretched vertically. Since you have selected nothing on the vertical side, the image gets stretched equally.
How does it look in-app? It may just be that the draw9patch tool is not previewing it correctly. Try stretching the window as wide as possible. Also checking the "show content" and "show patches" checkboxes might help to show you what the tool thinks is going on.
Also, be sure that the tray containing the stretch pixels is completely transparent, is exactly 1 pixel wide, and goes around the entire bitmap.
Related
As an addition to my previous question, I have a image and want to place text inside the image. I've created a nine-patch image but it scaled incorrectly - I want to leave part of the image unchanged.
original file
It's how it looks in editor
this how it looks in preview (and in my sample app with width more than image width
So I want to scale only text part and leave the 'head' and 'fingers' unchanged.
The upper part (black border) tells the 9 patch to stretch the "head part" too.
Please consider using two pixels at the sides of the "no stretch zone".
Something like: . .
This way you'd have 2 horizontally stretched areas, leaving the head unstretched.
[EDIT]
At last, I saw you put the image, so here's my patched version, just in case.
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.
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.
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
In Draw 9-patch, everything looks fine. However, my SDK says the 9-patch png is malformed. Because I have something like an 11-patch png. Because I don't want the little grabbing area to be scaled. How to get it working? The screenshot describes everything:
Error Meassage in Console:
ERROR: 9-patch image /res/drawable-hdpi/top_complete.9.png malformed.
Can't have more than one marked region along edge.
Found at pixel #10 along bottom edge.
ERROR: Failure processing PNG image /res/drawable-hdpi/top_complete.9.png
I believe your issue is that you're splitting the content area into two pieces which is not allowed. The top and left borders are treated differently by the tool than the bottom and right borders. The top and left describe what is stretchable, the bottom and right define content area (which must be contiguous).
Check the checkbox to show content area and play with it to see what I'm talking about.
I wouldn't split it into left and right, I would remove the == in the 9-patch and use this as a seperate image with center and bottom gravity so that is will always stay in the middle where you want it.
Just a hint: I always reduce the "scaled" part to 1 pixel width/height to get a minimized image.
9-Patch PNG without the grabber
XML of the Button:
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textStyle="bold"
android:textSize="11sp"
android:id="#+id/ButtonTop"
android:background="#drawable/top_just_bg"
android:drawableBottom="#drawable/top_dropper"
android:gravity="center"
android:paddingLeft="15sp"
android:paddingRight="15sp"
android:paddingTop="3sp"
android:text="There we go! It's working... ;)"></Button>
Is the use of Padding and sp-Values alright?
Since the original problem is not solved yet: You may split your image up into two layers, one NinePatchDrawable for the stretchable part and a solid one (centered) for your static image. Then just use a LayerDrawable to draw them on top of each other. Here is a good example of how to use the appropriate <layer-list> tag. That's how to do it the right way. ;-)
Split the original image in two and use those.
That image above looks fine, and the preview shows it's seemingly ok.
What's the error message from the device when you try to use it?
Are you sure that every pixel on the edge is either entirely white or black?
Even the slightest of transparency on the edge can upset Android.
Edit:
Ah ha, the error message reveals the problem.
Only the top edge of the image determines which areas will be stretched.
Remove the black pixels on the bottom edge, assuming this is just a grab bar that will have no content (e.g. text) inside it.
Otherwise, just fill in the central gap in the bottom edge, so that text content can be displayed in the purple area.
Review all borders ... Two in top and left (will be scaled) and 1 for right and bottom (will not be scaled).