I am learning about Android UI and am unclear why people use nine-patch, when you could use vector graphics, because those are scalable without any pixel degradation. I am a beginner in Android, so I hope I am not missing anything here, but it seems like it would be easier to build vector graphics and use those. You would not need the special editor to build them.
Can anyone explain the advantages to using nine-patch over vector? (Don't just explain advantages of nine-patch, as that is already done on StackO., but rather the advantages that vector does not have). Because it seems like Android recommends nine-patch. Thanks.
In vector graphics all side are scale or stretch when we set it to any background whereas in 9-patch we can define which sides can scale or strech so at runtime only those side scale which we set it to scale in 9-patch tool.
from this
-> The advantage of using 9-patch images is that when using it as a background, for instance, the image won't stretch and loose proportions in different screen sizes. the center 'patch' will remain as is and the 'borders' patches will be stretched to fit the screen/view size.
let say you have this image.
and a button with fill parent width. if you set this image to button background it will scale completely and your image gets blur (mean t will expand to button width)and it will not look good. so what 9 - path tool do that you define that online scale some part of image let say if width is fill parent. dont scale whole image . let say we set that after t (in image). scale whole area, so t will not get blur. so this will make good your button.hope you got my point..:)
after making your image 9 patch and setting to button background. your button look like this.
instead of t(in image). whole area expand and fill the buttons width.
Imagine a button with rounded corners. How do you scale it? If you scale it only horizontally, you will have elliptic corners, which would be ugly.
This is what 9-patch is for.
i hate 9patches. i am quite attentive when doing my artwork. i don't even use photoshop. i go with illustrator.
i do everything right when exporting my artwork, i used to do my 9 patches with insane zoom on, maybe check afther that in photoshop for misplaced pixels...
** sad trumpet ** when put on a view, if i used some subtle round corners like 6px or 10px and a stroke everything looks awful at mdpi.
So I solved my problems by marrying the two. I wrote my own 9patch which uses vectors. :)
Everything looks like it's been touched by baby Jesus. Perfect corners, strokes and, best of all, you can use one asset for all the screen sizes, densities while, of course, no more transparent borders, wicked errors because 9patch won't stretch inward, so on and so forth.
I use vectors for icons too. While there sometimes are issues with various effects, these are minimal and easily avoided if you do some reading on how to avoid them.
Best of luck to all you guys!
This is a very basic example.
You can do whatever strikes your fancy. Because of the performance impact of svg's on an app, when first run [or when the user changes appearance options, i like to save the newly generated bitmaps as pngs, if possible.
You don't get any more "best of both worlds" than this.
You can define content are on a 9-patch image which means (for example) text will always be placed in that specific area, I think you cannot do this in Vector image. Android has built-in support for 9-path but for vectors you have to use a library.
9-patch rendering is easy to implement and efficient. If you have an image that can be scaled by stretching horizontal or vertical lines (e.g. buttons or rectangular icons), then use a 9-patch. If you have some icons that don't scale well, then create multiple versions at different resolutions and use Android's resource management to handle it. Both of these approaches are much easier and more efficient than vector graphics.
If you have large images or scenes to render, and you don't want to take up a ton of space with bitmaps, thats when you start thinking about vector graphics.
Related
I have an button like this. I was asked to use 9-patch for android development. I am wondering how 9-patch is useful in this case. I am under impression that 9-patch scaling is for rectangular or squared which are in rounded corners so that even content inside grows the container stretches without the distortion. Please help me understand the actual purpose of the 9-patch scaling for Android. Thanks.
The content is scalable, the edges will not be scaled, in typical usage.
They're generally used for backgrounds to buttons, or other screen decorations, where the scaled content can be scaled infinitely without losing resolution.
Ideally, they're used in addition to density-dependent resources where appropriate, so that the section of the resource (which you didn't explicitly state is scalable) isn't upscaled and subsequently pixelated.
Consider the splash screen for the Kindle app on Android, which features a silhouette of that boy reading against a tree. In a simplified version, the ground can be scaled horizontally infinitely, but if the boy was scaled, he'd appear skewed. So you could use a nine-patch and specify the section which can be scaled, and in which direction.
That's not enough though - if you only included a low resolution resource, the resource would still be scaled up initially if the device display was of a higher density. In this instance, the boy might look blurred from the upscaling, and is an example of when a higher resolution resource could have helped prevent the pixelation.
The way you've phrased the question suggests (to me) that you're asking whether 9-patch images can replace all drawable resources, like icons or resources with pictures in them, to which the answer is no. They're only to be used to scale sections of resources which feature a block of a single colour (i.e. sections which cannot be pixelated).
--
http://developer.android.com/guide/topics/graphics/2d-graphics.html#nine-patch
Please help me understand the actual purpose of the 9-patch scaling
for Android
There are many situations where you find yourself needing the same button style but in different sizes.
So in that case you will have to provide different size resources. But to avoid this, you can simplly provide a 9-patch image, which will be used irrespective of sizes.
Advantages of using 9-patch:
When used as background,image won't stretch and loose proportions in different screen sizes.
Saves memory.
9-patche images are small, reusable and scale nicely.
If you don' use 9-patch images, you will need to test on various sized screens.
9-Patch
A guide to 9-patch
I have an iOS app that uses unique textured backgrounds (think of a game title screen or something) on each of the screens that I am trying to port to Android. On iOS they knew the resolutions and just designed the backgrounds around those. Obviously that isn't possible on Android.
What is the best way to put a textured/non-repeatable background into Android that works on various screen sizes and aspect ratios?
The solutions I have thought of so far are:
Fit the shortest dimension and allow the image to go off the edge of the screen for the larger dimension
Make the background image large and center it, then make it stretch out beyond the edges when the resolution is smaller than the image
Stretch the image to just fit (this is ugly and I'd like to avoid it)
Create a different version of the image for each resolution. (This seems way beyond the scope of what is possible for this project.)
As far as I can tell in Android, 1. and 2. aren't possible out of the box because background images set the size of the view to match their size (you can't tell it to just extend beyond the edges, please correct me if I am wrong).
What solutions would you use in this situation?
Use an (match_parent) ImageView to simulate back ground image. (By adjusting the scale type of imageview you can get the result of point 1,2)
http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
Use 9-patch image. You can specify which part of your image can be stretched. For your case I suggest adding a small "margin" to your image, and make it stretchable using 9-patch. Only the margin will be stretched, maintaining the aspect ratio of your image.
android developer 9-patch
Create a different version of the image for each resolution.
As you're probably aware, Android can run on a wide variety of devices with varying resolutions and screen densities. To be fully compatible with all of them takes a bit of graphics work; you need resources for each possible screen density (and in this case, resolution).
For full details, see Supporting Multiple Screens in the Android developer documentation.
Unless something has gone seriously wrong in your development process, you should have the original files (e.g. .psd) to work with when creating these resources.
Is there a way to scale buttons in such a way that the do not loose their 3D effect. Since everything is beeing scaled proportionally the 3D border of a button becomes too large when the button scale changes.
On iPhone there is an attribute that can be set so that this does not happen and the button looks good in whatever size.
Is there anything like this on Android?
Or how would one setup a button so that scaling looks good all the time?
Many thanks!
You could make 9-patch button backgrounds using draw-9 patch in the Android SDK bin folder. These will scale very nicely from a very small sample/drawable.
I have some large icons, which are 9patch, and have to create a smaller set for a smaller screen. If I use something like photoshop to do the resize, are they still 9patch?
I just uploaded on code.google.com a tool that does the resizing for you :https://github.com/redwarp/9-Patch-Resizer
It's really simple : just drag n drop a xhdpi 9 patch, and it'll create the lower densities (ldpi, mdpi and hdpi).
Hope it helps !
Edit : moved to github
Nine-patch image is usual .png image with 1-pixel black border (link). I think if you may edit it PhotoShop. Note that border can't be broken.
Another way is: edit source image in PhotoShop and use Draw 9-patch tool to create 1-pixel border. It includes in standard Android SDK and it is free.
No, they are no more 9patch.
Say we resize 8x8 to 4x4, there 4 Pixels from the original made to 1 pixel(simplified). So you loose much information.
When resizing from 256x256 to 255x255 the loss of information is so small, that there is a good chance for the borders to stay 9patch-compatible.
The only method to resize these images(by very small factors) is "Nearest neighbor", because all the others use interpolation of colour-values with the surrounding pixels(the black border becomes gray).
In your case of app development, i would take the time and use "the other way" from "Dmitriy_Boichenko"'s answer and do the 9patch-thing from ground up, because graphics bugs are unsightly.
you can edit 9-patch inside photoshop of course.
In fact, you can edit in any editor supporting png.
It's a simple PNG file in the end.
There is only 2 very important rules:
File extension must be .9.png
The border around the image must be one pixel wide and contain only pure black or fully transparent pixel.
There is no need to create different density if you do it well, unless you don't like the look once it is scaled up or down.
Now since you mentioned icons, I wouldn't do Icons using 9-patch.
I would create 3 different density for each Icon.
Follow the guidelines here: http://developer.android.com/guide/practices/ui_guidelines/icon_design.html
I used a linear gradient image for a background and in Photoshop (and everything else) it looks nice and smooth but when I displayed it in the emulator is was banded! What's worse, it's banded on my actual phone - a Droid Incredible. I'm running 2.2 both in emulation and on the phone.
Here's a sample - original on the left, Android'ed version on the right: http://pnart.com/temp/AndroidMach.jpg
This has the appearance of Android imposing some bit-depth limitation. What's going on and how do I fix it?
Thanks in advance!
I had the same problem and did some searching on Google. One of the sites I found suggested I put the gradient image in res/raw/ and load the image when needed. I tried this and it worked.
From what little I understand, any image you place under "drawable" will be processed by AAPT and it isn't guaranteed the final images will be the same as the ones you are putting into it. In this case, it decided to shrink the PNG gradient image to a smaller palette to shrink the size of the final APK. If someone else has a better (or more correct) explanation, I'd love to hear.
-Dan
just try this: get down the width and height to the screen resolution of the device (eg: for moto droid: w:320px and h:480px and in photoshop keep the resolution to 200 dpi or above)
Regards,
Mistry Hardik
If there isn't any special reason for using an image to get a gradient I highly recommend looking up the Shape Drawable as it supports gradients which should (I haven't tried it but I assume) allow lossless scaling.
First of all, the color depth of phone's screen is much worse than that of your PC. On your PC you have 8-8-8 bits depth for R-G-B but for phones it's typical to have 5-6-5 depth. It means that any fine gradients/shades that look good on PC will be distorted when displayed on the device because its color depth is just not enough, physically.
Therefore, designer's rule №1: avoid fine shades and fine gradients in your designs.
But if you have to then, of course, you may try the following, but you've been warned!
1) For runtime-generated gradients: use dithering, like this:
setContentView(R.layout.screen_dashboard);
findViewById(R.id.layout).getBackground().setDither(true);
2) For graphics assets: always apply a 5-6-5 filter before saving png. Here is a good article with examples. Applying 5-6-5 filter ensures that color depth of your png is within device capabilities, and decreases png size too.
Seems like it might be because it's scaling the image to fit the screen. When non-vector gradients are scaled they often get that "banded" look. Try making a gradient that's the same size as the screen you're targeting, or try changing the ImageView (or whatever) that is displaying the image to make sure it's not stretching or scaling the image.
EDIT
In my opinion the best solution would be to create your gradient for your background at runtime have a look at GradientDrawable