We use 9png mainly to reduce the size of the apk. But, I am facing a peculiar problem. I am not sure in which folder I have to place the 9pngs in. I had put them in HDPI folder. Since Android is 'clever' it looks like if I use the app in an MDPI phone, it 'scales' the 9png which creates crazy effects. I didn't face any major problem until I tried it in Galaxy note. Looks like the 9png was taken from HDPI and scaled (Note has 800x1280) and it created weird effects.
So which is the right place to put the 9pngs?
How to tell Android system not to 'scale' 9pngs based on the folder it is put in?
According to Romain Guy's answer on Google groups:
The behavior of 9-patch is undefined when shrunk. In practice you will
see overlaps of the various sections of the 9patch. Don't do it :)
From what I noticed in my projects, a 9PNG is scaled down just like any regular PNG, so I am usually requesting to our designer the entire set of images for ldpi, mdpi, hdpi and xhdpi, and I transform them all in 9patches.
That, unless there is a very simple 9patch, like a plain button background, that makes no difference when stretched or shrunk, so I usually place it in the regular drawable folder.
I had a similar problem with a nine patch image: if I placed it in the res/drawable folder, it didn't work on an ldpi screen (it distorted the image and lost the transparency).
The solution for me was to put it in the res/drawable-nodpi folder. The documentation states:
This can be used for bitmap resources that you do not want to be
scaled to match the device density.
Just put the 9png in your HDPI folder.
if the effect looks weird in your Galaxy Note.
Ask the designer to give you a new 9png file for the XHDPI. and then put the new file in folder XHDPI.
Related
So far, I always created one nine-patch image and place it inside /res/drawable-hdpi.
But I saw some large projects which have multiple nine-page images, scaled and placed inside multiple res/drawable-xxx directories. Is this the wrong approach? Nine-patch was supposed to stretch across all screens, regardless of its DPI.
Also, if I am right and only one nine-patch is to be used, what is its default location - drawable-hdpi, mdpi, or some other directory inside /res?
Well, it really depends on quality.
If your image is just a square border, it can be a 72 dpi low res image put into the drawable folder and it would be enough.
If your image has rounded corners or other fancy elements that have to be scaled properly, you could make a 480 dpi version and put it in the drawable-xxhdpi folder. This will scale down (don't even think of scaling up, because of stretching/pixellating) good enough in most cases.
If you want the best quality in scaling, then make a version for each dpi drawable folder.
If you go to http://developer.android.com/guide/topics/resources/drawable-resource.html, you can see it there (citation):
file location:
res/drawable/filename.9.png
The filename is used as the resource ID.
Last two questions stayed unanswered, I hope "third one's the charm" works :)
I want application that is HDPI use those drawables in folder "drawable-xhdpi" and LDPI devices those in "drawable-mdpi". So I don't have to duplicate same images. Is this possible?
Yes, Android scales drawables, selecting the drawable that will produce the best result. But not all scaling combinations work that well. Downscaling to MDPI can produce noticeably poor results. XHDPI to HDPI generally produces pretty good results. But given that the overwhelming majority of devices these days are HDPI, it's probably worthwhile to have HDPI resources. HDPI to XHDPI scaling is not terrible. Some 1280x720 devices uses XHDPI resource. These generally look ok. Google TV uses XHDPI as well. On a huge screen, scaling errors are visible.
LDPI devices are -- for all practical purposes -- non-existent now.
True that generating scaled resources is an enormous PITA. But, in my opinion, you really need to do MDPI and HDPI. And once you've got that unpleasant workflow down, it doesn't require a lot of extra work to generate XHDPI. For what it's worth, if your artwork is in vector format, the vast majority of resources don't need tweaking for specific resolutions. There doesn't seem to be any compelling need to pixel-align edges of square objects, for example. Usually it's only interior features in complex icons and artwork that benefit from some amount of pixel-pushing.
It's pretty clear that XHDPI is going to be come more and more common. Trust me, you don't want to go back and re-do all your artwork in XHDPI after the fact. My advice: if you intend to still be shipping your app a year from now, suck it up, and do the nasty as you go, while it's still relatively easy.
In my experience, if you place an image in just some of the drawable folders, but not all, the OS will choose the "best" image for the device that you are using, even if it is not exactly the perfect fit. For example, if you put an image called arrow.png ONLY in the drawable-hdpi folder, all devices will use that image for the arrow drawable, and scale it down or up appropriately, stretching or shrinking the image.
That being said, you should be able to accomplish what you want by simply putting your image in the right folders and allowing the devices to choose the correct one. For example, if you were trying to accomplish your task with only one image, arrow.png:
drawable-xhdpi/ -> arrow.png
drawable-hdpi/ -> empty
drawable-mdpi/ -> arrow.png
drawable-ldpi/ -> empty
drawable/ -> empty
If you use the app on an ldpi device, the device will use the mdpi image, as you wanted, because it is closest to the correct resolution. On the hdpi phone, it will use the xhdpi image, because it is again the closest to the correct resolution.
Yes. Android automatically downscales/upscales resources that it cannot find. If you were to only put resources in the XHDPI folder it would just work, Android would take care of resizing them to work in all the other densities.
We should add this code in MainActivity class and copy image to dhpi folder with ic_launcher, ic_launcher2, ic_launcher3 and ic_1 is image name, we can change size: width and height
int array_image[]={R.drawable.ic_launcher,
R.drawable.ic_launcher2,
R.drawable.ic_launcher3,
R.drawable.ic_1
}
I have a quick question: will it work when I put the same 57px x 57px icon to all drawable-ldpi, drawable-mdpi and drawable-hdpi folders. Will it run on all devices?
in other words if small icon will be visible on big screens or x-large screens.
It will work, but you really should not use size of 57x57 for any screen size - scaled down images will look as ugly as scaled up. Better avoid it.
Please read more here: http://developer.android.com/guide/practices/ui_guidelines/icon_design_launcher.html (yes, it is an official documentation).
Yes, it'll work. But it is good to have all icons. Because it'll be pixelat on large screens.
If you simple put icon in drawalbe folder (which is default folder) and you don't have any other folders like hdpi, mdpi, ldpi for all screen sizes. then it'll also be considered for all resolutions/sizes.
It will work. But it will not look well on some screen.
My question is straight forward and simple, Like there is layout-sw600dp,values-sw600dp, for layout and values respectively, what is there for drawable folder in relative to size of screen.
I read in various document that if we want to use any screen more than or equal to 7 inches we can use layout-sw600dp folder, and for any lesser screen size device, layout folder will be taken into consideration. So how we can make use of same concept for images also. Right now there are ldpi, mdpi, hdpi folder, but images are taken in accordance of screen density not with screen size.Now if I am developing an app which work both on device and phone, what should be my probable approach for images.
Thanks in advance, please guide me.
you can also use the same concept for drawable like drawable-sw600dp,drawable-sw600dp-mdpi etc. I have used this in my application .
I'm not 100% on this one, but I think you can also use the same convention with drawables. Try drawable-sw600dp-hdpi or something similar. Though I also do have a few questions you may want to answer before proceeding:
Why would you want a different image (not resolution) for a bigger screen size?
As you already know, a 7-inch device would be using the layout-sw600dp folder, so why not have a different name for a different drawable? That would look a lot cleaner, imo.
I'm currently looking into getting my android app to work on Kindle Fire. I've got artwork for both MDPI and HDPI screens, but I noticed that when I load the app up on the Kindle, it displays the MDPI artwork and stretches some of my artwork that I'm filling parent with a little more than I want.
I was wondering if there's any way on Android to under certain circumstances (like if I'm on a Kindle), force it to load from the HDPI artwork, instead of defaulting to MDPI.
I do realize that I could just save my HDPI artwork in the MDPI folder with a slightly different name and do a check for every resource, but that's a lot of overhead, not to mention an increase in the size of my app, which I'd also like to avoid.
Thanks
Update: Still looking at this one. I guess what I'm really getting at, is there a way for an android device to chose HDPI artwork instead of MDPI, even though the MDPI artwork exists?
The Kindle Fire is 1024x600 with 160 dpi, right?
You can try new resourses with that resolution. And place them in the MDPI folder.
Add layout-large at /res directory and copy your layout file there.
That way, with the Kindle Fire, you use the layout at layout-large pointing to bigger resources in the MDPI folder.
And make sure you always use nine-patch drawables for resources.
Hope this helps you.
Ended up using a hack solution in the meantime, but I came across this:
I don't want Android to resize my bitmap Automatically
Pretty much just needed to move my hdpi images into the nodpi folder (in order to avoid the scaling issues) and changed the names slightly (I added a _hd to the name). After that I made an image loader that takes in the name of the image I want and returns _hd images if device is hdpi or if it's kindle fire:
id = ctx.getResources().getIdentifier(string + "_hd", "drawable", context.getPackageName());
Note: The docs do discourage the use of getIdentifier(), as it is less efficient than just using the resource address, but I took a look at the load times and loading 1000 images with getIdentifier takes .25 seconds, which is fine with me especially since I'm not loading anywhere close to that many images.
You can try new resources with that resolution and place them in the MDPI folder. Add layout-large at /res directory and copy your layout file there. That way, with the Kindle Fire, you use the layout at layout-large pointing to bigger resources in the MDPI folder.