Everytime, when I supply resource to drawable folder, here is what I did
drawable-xhdpi (96x96 px)
drawable-hdpi (72x72 px)
drawable-mdpi (48x48 px)
drawable-ldpi (36x36 px)
Most of the time, I merely use GIMP to perform dummy scale down from the largest size image from drawable-xhdpi. I do not perform any further pixel editing on the scaled down image.
Recently, I realize, if I only supply 1 highest resolution image, Android system will internally perform image size scale down.
drawable-xhdpi (96x96 px)
drawable-hdpi (empty)
drawable-mdpi (empty)
drawable-ldpi (empty)
I tested on 2 devices. It works for me. I was wondering is this a good technique to avoid cumbersome work to supply so many different size images? Any side effect on this technique?
I was wondering is this a good technique to avoid cumbersome work to
supply so many different size images? Any side effect on this
technique?
I imagine there are (at least) two:
This may not always work with 9-patches, especially if the stretchable area is defined by one or more single pixels. For example, if you would provide such a 9patch as xhdpi drawable, then on an mdpi device that single pixel will effectively be 'halved' and thus either disappear completely or blended with the surrounding transparent pixels. The latter is generally true for any upscale/downscale operation, so it's quite likely that your 9patch will not appear as intended.
Larger images will simply take up more space in memory. Especially on low(er)-end devices, with a limited amount of internal memory and a reasonably strict heap space limit, you're likely to run out of memory fast when loading images way larger than required for displaying.
Regarding your comment: it's fairly easy to come up with a sample 9patch that will not visually look as intended across all different screen densities if you supply it only as xhdpi resource. Consider the following 9patch:
Enlarged snapshot for the sake of visibility:
Obviously, the idea is that when this 9patch gets stretched, the result is a 1-pixel thick horizontal blue line. Now, drop this 9patch in just the xhdpi folder and compare the results on xhdpi vs. mdpi:
Clearly, the mdpi device has scaled down the 9patch from the xhdpi folder and the result doesn't look like intended.
Anyways, my point is that in a lot of cases not supplying 9patches for every density bucket may end up looking fine. Just be aware of the fact that there are definitely scenarios out there for which it may not give the desired result. Also, take into consideration the memory argument.
The technique you are using will work on fewer number of devices..
Because in market there are a lot of phones with different resolutions and different sizes.
In some low resolution devices whose screen size in smaller,the UI will not look proper...
Now take an example that you are using a background image for splash screen whose resolution is 720*1280(xhdpi) and you have put it in Xhdpi drawable folder than when you view this drawable in low end device like Samsung euopa or HTC wildfire the image would look squeezed type.
there would be a lot other situation where you would be required to use different set of images....
If the technique mentioned by you would work in all phones then why would had Android developed different folder for different set of images.... :P
Related
I have read on this forum that the answer is to split the image in different resolutions and put it in different folders and the other way is to put the image in one folder without splitting it up so that android doesn't resize it.
My question is in which folder exactly do we put it on so it doesn't resize itself and shows as it is?
My res folder looks like this
Based on your updated question with the image and the clarity.
You are asking how to avoid scaling. You can either use the drawable directory or the drawable-nodpi to avoid prescaling. Either one will work for you.
I made a document on this once for the UI team I was working with, so this document is a little specific to their request and that app, but it might help you.
https://drive.google.com/file/d/1gJjT-F5AU57TCAr5I18l0jAvNG5-vLUb/view?usp=sharing
For vector drawables just use "drawable" standard directory. Make sure you are not violating any of the unsupported tags such as gradients and linear tags or you will have issues.
Next the -24 -26, etc.. folders are used for version specific. For example, let's say you have one type of image for pre 24 Android, but a different type for post 24, you can use -24 for the post image, and all others will check standard folder for it. This sometimes happens when you use something bleeding edge that isn't supported back far enough for your app's minimum SDK. You are not likely to use this for images, I can't even think of a problem where this would arise in the image buckets, but it's there all the same.
For deciding what resolution you need for each bucket, there are a couple of options here. First you could simply do the math. Decide how many inches you want it to take up and determine how many pixels are needed to accomodate that size and label that MDPI, than scale from there using the multipliers. Another less mathematical solution would be to open a preview on Android select an MDPI device and start playing with width = 100px height = 100px and adjust until you like the size. Write that down, it is MDPI, and begin your scaling from there.
As for a rough estimate of pixels to size, you can see what an app icon looks like and see what Android uses for that below.
So even though each bucket has a different pixel by pixel resolution, they will be identical sized and pixels per inch resolution on all devices due to bucket placement.
Hopefully that all makes sense.
--I'll leave the below from the original answer in case it helps someone--
You may have gotten some bad information.
https://developer.android.com/training/multiscreen/screendensities
Android is a widely dispersed resolution and size market.
In order to accommodate this they allow for DP and Buckets.
There are buckets for languages, screensizes, orientation, and resolutions.
You are looking for resolution support.
drawable-ldpi -.75 multiplier on size (1dp = .75px)
drawable-mdpi -baseline 1dp = 1px
drawable-hdpi -1.5x multiplier on size (1dp = 1.5px
drawable-xhdpi -2x multiplier on size (1dp = 2px
drawable-xxhdpi -3x multiplier on size (1dp = 3px
drawable-xxxhdpi -4x mulipvlier on size (1dp = 4px
each bucket has a multiplier associated to help the image look the same approximate size on each device. So even though it is 1 inch by 1 inch on one mdpi phone with your 100px x 100px image (pseudo size, don't calculate it ;)
it will need to be 150px x 150px on the hdpi to have the same quality and resolution of pixels per inch.
Now if you put all your images in the drawable bucket. Android will just ignore the scaling of these and you end up with varying space consumption depending on the device which will be very inconsistent on how much space it takes up on each type of phone.
If you put all your images in the correct folder you will at least have better quality. For example, let's say you have maybe 750px x 750px image that is meant to fill up a 1 inch area. You would be better suited to put it in the XXHDPI folder or XXXHDPI folder so Android knows to scale it DOWN rather than UP. This will give you better resolution for each device resolution that it scales for.
However, this is still poor practice. You are relying on Android operating system which can be very slow and weak on many cheap devices to do your scaling for you. I would recommend using GIMP and scaling to each multiplier on your own, then putting it into the respective resolution buckets.
This way Android decides based on the device which bucket resolution image it needs which decreases the amount of scaling exponentially.
Now, if you have Vector Graphics that you have imported, those will end up in the drawable folder which tells Android to ignore the resolution, and just draw these as vector graphics. This is the best option in my opinion as you only need one set of images per image. Although, Vector graphics aren't quite as fast at loading as a JPG or PNG, but it keeps your package size down quite a bit and development maintenance is so much nicer.
Hope that helps.
Happy Coding.
I'm currently working on 2 Android projects and seems like I have a problem with understanding how to handle the density of resources. I have a HTC One M8, which has ~440 dpi, therefore I'm using XXHDPI. I always use XXHDPI resources and wrap content for the elements. On one of the projects, all the resources are png formats, again using XXHDPI and wrap content and when running the app, it looks great.
On the other hand, the resources from the other project are .9.pngs. Whenever I use XXHDPI and wrap content, in the preview, the design of the elements is altered, the pictures are really shrank.
However, if I use a HDPI, the size of the picture will look good, but the pixel's density will be crap. As far as I know, I should never hardcore the width and the height of the picture, but get the picture with the specific density and just use wrap content.
Am I missing something or there is a problem with the resources?
i just released my app on android and have problems with customers with high density displays.
i added a debug thing to see what's going in, here is one sample output
Device: Nexus 10 Android version: 4.2.2
DisplayMetrics{density=2.0, width=2560, height=1504, scaledDensity=2.0, xdpi=298.275, ydpi=298.823}
MainView w=1900 h=1342
mDrumKitMode=BIG
KitView w=640 h=1266 x=1920.0 y=0.0
the main view is the music notation area on the left of the screen shot, its 1900 wide (MainView w=1900 h=1342) the drum kit is a bitmap that is 640w and 640 high. somehow, the display is scaling it to be full height of the parent, (KitView w=640 h=1266 x=1920.0 y=0.0). this doesn't happen on displays where density=1.0.
i have no way to test this since i can't get the emulator work on big displays for some reason and i don't have a high density tablet.
does anyone have an idea what could be going on? thanks
and here's another customer with a similar problem
Device: A700 Android version: 4.1.1
DisplayMetrics{density=1.5, width=1920, height=1128, scaledDensity=1.5, xdpi=224.73732, ydpi=224.11765}
MainView w=1260 h=1044
mDrumKitMode=BIG
KitView w=640 h=968 x=1280.0 y=0.0
i think its the scaledDensity=1.5 parameter, maybe i need to do something to disable automatic image scaling, i.e. set scaledDensity=1?
i should add that the entire application is based on exact pixel positions, both for the music notation display and the drum kit display which overlays images on top of the base drum kit image (you can see the drum pedals are in the wrong place on this image too). i don't want automatic scaling as i handle scaling inside the app for different display sizes and user preferences.
i should also add that all my drum kit images are in drawable-mdpi and all the other dpis are empty. this is because i scale images programmatically based on screen size and user preference BUT i think maybe the problem is a need to put some images in xhdpi? i guess i can do that but it will be a lot of work.
PS, i guess i found my answer here http://developer.android.com/guide/practices/screens_support.html
Provide different bitmap drawables for different screen densities
By default, Android scales your bitmap drawables (.png, .jpg, and .gif files) and Nine-Patch drawables (.9.png files) so that they render at the appropriate physical size on each device. For example, if your application provides bitmap drawables only for the baseline, medium screen density (mdpi), then the system scales them up when on a high-density screen, and scales them down when on a low-density screen. This scaling can cause artifacts in the bitmaps. To ensure your bitmaps look their best, you should include alternative versions at different resolutions for different screen densities.
i wonder if simply copying all the -mdpi images to -xhdpi will work?
If you intend for this app to be used across devices you have no choice but to put in images for all the various density folders that exist (xhdpi,xxhdpi, hdpi, mdpi). It's also worth considering that you may want to change the actual layouts you include, to offer different ones for different devices.
Consult the documentation for how to handle this.
http://developer.android.com/guide/practices/screens_support.html
If that creates an apk that's too heavy (I have no idea how many images you have) then you can go the other way and specify a no scaling drawable folder which will just use the images in their native density across devices. It's definitely wrong to use ONLY mdpi unless you intend to support only mdpi devices.
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 game which displays a full screen image in the background. At the moment I have one image size (1280x800). This works well on large resolutions but on smaller screens the shrinking somewhat degrades the image. You can see jagged edges and it is noticeably worse than what you could achieve using photoshop software.
I have different image sizes, but I am unsure how to utilize them. I know there are different dpi folders, but you can have resolutions of 480x320 and 1280x768 with the same dpi so I don't think these can be of use here.
I believe you can have different layout files for different screen sizes, but the image is not drawn using xml (and in fact would not be possible for my game).
I can only think that I must create a different file name for each size. Then when choosing which image to use I could take the screen dimensions and select the correct one? I am struggling to see how I can make an image look good on both 240x320 and 1280x800 resolutions.
All of the resource qualifiers in the framework can be applied to drawables, not just the dpi designators. In other words, you could create folders like this to segment your images as well:
drawable-ldpi
drawable-xlarge
drawable-normal
drawable-sw480dp
drawable-sw720dp
Even examples like these work...
drawable-v10
drawable-land
And so on...
You can create as many or as few different qualified directories for your image assets as you think necessary to preserve the quality. The Supporting Multiple Screens article in the SDK docs helps describe most of the qualifiers that best fit scaling image assets.
HTH!