9-patch background renders with artifacts and cropping - android

I'm using a 9-patch file for a button background, and while the draw9patch tool validates the file, in Android Studio it renders with artifacts and cropping. I'm not sure if this is a bug in Android Studio or a mistake in my 9-patch. Here is the code for the button, if it helps.
<ImageButton
android:layout_width="fill_parent"
android:layout_height="40dp"
android:id="#+id/imageButton"
android:layout_weight="1"
android:src="#drawable/tool_panel_share_icon_default"
android:baselineAlignBottom="true"
android:background="#drawable/view_type_button_background_left_default"
android:scaleType="fitCenter"
/>
Here's my 9-patch:
this is what I think it should look like on the button:
but this is what I'm actually getting ( the bottom line is a 26% transparency over a dark background ):
you can see that there is an errant black line on the left, and the black line that should be on the right is apparently cropped.
Update:
Here is the actual 9-patch file, what I posted earlier was a screen shot of the file, for the sake of seeing the fine details.
Update2:
Ok, I figured out how to make it display correctly, but I still don't understand the reason for the initial failure. I realized that if I place the top marker next to the off-black line that is part of the 9-patch content, it fails; however, if i move it 1 pixel to the left it renders correctly.
Works:
Fails:
Here is the new 9-patch and a screenshot of the successful rendering:
Update 3:
I just recreated the 9-patch using the draw9patch tool and the behavior is the same.

I downloaded the 9patch png you provide, the following image is the left black dot of your png, which is not correct. The borders of the 9patch pngs should be only 1 pixel width, and could only use black as its color, which is (0, 0, 0).
Look this page for more information.

I have face the problem similar to your once.
I guess you place the nine patch image in folder with lower resolution than device.
When device try to get the image it need to scale the image up and your top marker is right at the "border" which is the gradient area .
This can result in unpredictable image after scale.

You make it too high.
Try to make it like i post.

Do you use
...\Android\android-sdk\tools\draw9patch.bat
to draw your image? It's really helpful and show preliminary result.

Related

9patch images stretching incorrectly

(The black lines are not visible so I just made a replica of it in photoshop and enhanced the black lines for you people to understand. )
( The black lines are photoshopped. JUST so they look a bit visible here. )
Suppose, this is the 9patch image, i have broadened the 9patch black line in photoshop so its clearly visible.
This is how it is going to stretch. The logo remain in its original dimensions, only the blue space will stretch.
In the 9patch software, the X and Y coordinate results were perfect and they stretch the way they should.
However, when I insert this in my xml code, I get this result.
WHY is the logo part stretching ?
WHATEVER the dimensions of the layout may be, the logo should be in its right size , while the space around it SHOULD adjust , but its not happening so.
Edit::
The images in the jar preview fine, but when I actually use that resource in some layout, I get the incorrectly rendered result.
The xml code for the button :
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button_normal" />
You do it wrong, To make a 9patch using photoshop:
1- add a new transparent 1-pixel in each image side (left, right, top and bottom)
2- draw the scaling and content in that transparent pixel (black color #000000), not over the image content it self.
3- save it as your_image_name.9.png
This is my version: logo.9.png
As you can see, it works just perfectly
Make sure you put it in the /res/drawable folder and it ends in .9.png

What's the issue with this 9-png , showing black borders?

I have been struggling for a week to run this nine patch image by adding patches to it with all case but it doesn't work , I can't figure out why ? Any suggestions are highly appreciated.
It shouldn't show black lines when I am using it.
This is the layout code where I use this image ,
<Button
android:id="#+id/answerA"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_marginRight="2dp"
android:layout_weight="1"
android:background="#drawable/d_grey"
android:gravity="center"
android:onClick="AnswerCheck" />
--Edit--
As suggested in an answer I opened this image in ninepatch tool and below is the screenshot for the same,
Possible solutions:
Have you created 9-patch images properly? check out this site
and create 9patch image.
Do not remove .9 extension from image like sample.9.png
Do not resize image after creating 9 patch image.
Refresh-Clean-build project to apply changes you made in resource
folders
Looking at your drawing, my guess is that you have far too many patches, probably around 18 patches instead of the usual 9.
Load the nine-patch into the Draw 9-patch tool (which is in your Android sdk under tools/)
Then select > Show bad patches
Update:
Take a look at this image (taken from this technical blog)
For me at least, that's what I envisioned a 9-patch to be, that there were 9 patches in the png. In your latest drawing however from inside the draw-9-patches tool, I think I'm counting 20 patches
That being said, I'm not sure if what I'm saying is correct. If you have bad 9-patch, the tool should at least be showing you the bad patches surrounded by red lines. And so, it could be that both the blogger and myself are incorrect.
I often encountered this issue also and I usually avoid to put the back line on the very edge of the image.
Try to do it as you did it on the bottom of your image and leave at least 1 pixel on each edge without black otherwise it is not correctly rendered.
I encountered this issue on a xxxhdpi screen. Android doc says for xxxhdpi: "Resources for extra-extra-extra-high-density (xxxhdpi) uses (~640dpi). Use this for the launcher icon only, see note above." In my xxxhdpi device, the 9-patch image was displayed with the black lines borders because of that. When removing the xxxhdpi 9-patch, the display issue was fixed.

Android nine-patch not being recognized on device

I just made a nine-patch
it is saved like border.9.png from the draw 9 patch tool.
in my android layout editor, it shows up like it is going to be a proper 9 patch graphic, stretched out yet not pixelated.
yet on a real device, it just shows a giant stretched image, with the 9patch guides seen, it looks really bad
whats going on??? and how do I fix it
my xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/border"
android:orientation="vertical"
android:padding="35dip" >
I just had the same issue : everything worked fine in Eclipse but all where streched on the device.
I solved it by opening the PNG in the Draw 9-patch tool.
Just open the png and save it et voila !
You can find all the necessary information how to create a 9.patch here
Your background should be like this
Note: the markers to the bottom and right need to be drawn as complete lines, not single dots.
Edit
Seems that uploading the 9.patch here becomes altered, and cannot be used as a 9.patch anymore. You can download the functional version from here
This looks like invalid 9.ptach file to me. There should be solid regions at the bottom and on the right side.
As a last resort, whenever you're having a tough time getting a 9 patch to be recognized as such, I find it's always best to just make a BRAND NEW image file in your imaging software, copy all except the 4 1-pixel borders of your original image, then paste into your new image file. Sometimes no matter how much you delete away the 4 edges, the device/emulator still can't recognize it as a 9-patch, even though (and this should probably be of concern to the Android SDK dev team) it's a perfectly fine 9-patch in Eclipse's Graphical Layout.
Also note, black lines on the right and bottom edges are optional. They specify "padding", in particular the region where the content (the child of the parent with the 9-patch background) fits.
It took me some hours to figure out, why my nine patch didn't render right.
The reason was quite simple. My nine patch image was stored under:
/res/drawable
instead of
/res/drawable-xxx

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

Android / 9-patch PNG: What, if I need smth like a 11-patch PNG?

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).

Categories

Resources