Why the need for drawable folders? - android

I have always noticed that i have many drawable directories - drawable hdpi, ldpi, mdpi, xhdpi. I know that these directories are for different screen densities(scaling up purposes, like android will use an image from hdpi if your screen has that screen density. But isnt that the whole point of the unit dp? Why invent the wheel again?

When you describe a view size with dp units, you're only saying how much space it should take up on the screen. In the case of of a drawable, the renderer will scale the raw image up or down to fit your dimensions. The reason for the different drawable folders is to optimize for different resolutions.
On a screen device with higher pixel density, the interpolation performed by the renderer will make a low resolution raw image look blurry, which is why we need high resolution assets.
On a screen with low pixel density, the renderer can and will scale down high resolution images when low resolution ones aren't present, but this is wasteful. First of all, the interpolation performed by the renderer might give you an ugly result. Secondly, the raw image is decoded at full resolution only to be displayed in a view of a much smaller size. Thats wasting CPU cycles and memory, both of which tend to be less plentiful on devices with low pixel densities.

Related

Pixel dimensions for different DPIs for a full screen image?

I'm trying to make an activity with an image that is the same height as the screen. I tried going to easy route, and just using a really big image and then scaling it down within the app, but when I run it on a device with a smaller screen, I get an error saying the device ran out of memory. I was hoping to make several drawable folders for each dpi (drawable-mdpi, drawable-hdpi, etc.). I looked up the pixel dimensions for splash screens, but when I resize my image to fit those dimensions (https://stackoverflow.com/a/15744389/5909429), the image only fills about half the screen on my smaller device.
What dimensions should I actually use, or am I using the drawable folders wrong?
[...]or am I using the drawable folders wrong?
Yes and no. I don't know about any "perfect" values for your picture dimensions, and I doubt that there are any, due to the fact that there are too many different phones to support.
The usage of dpi ensures that everything has the same size. If you were to put a ruler on your screens on a xxxhdpi and a ldpi device, both pictures would be the same size. This is dpi.
What you are trying to do is filling a phone screen. This has not much to do with dpi, but is about the actual pixel size of the screen. If you have a 1920x1080 phone display, you want an image with the same resolution. This does not say anything about dpi or screen density, and it has frankly nothing to do with it.
To properly scale down your image—and not running into OOM—you can either use a designated image loading library, like Glide, or Picasso, or you can take a look at BitmapFactory which lets you supply a inSampleSize to load the image in the size needed yourself. The official documentation can be found here at Loading large bitmaps efficiently.

What happens when you do not place an icon in all possible sizes in your res folder?

I am wondering what would happen if you put for instance one image in only one specific size, let's say image X in hdpi and an other image Y in only resolution size xxhdpi, the size which was "right" for the device was xhdpi. Assuming that the OS decided what was the "right" size for the device.
Will it then downscale the image xxhdpi and upscale hdpi to xhdpi? Or would it only change the size of one image, for instance the one with the lowest resolution remains the same, the higher ones are downscaled?
Quite an interesting question out there!
In this case, the bigger drawable will be taken an downscaled to the device needs.
However, if the device is i.e. xxhdpi and you provide drawables ie. for mdpi and hdpi, the OS will take the hdpi drawable and scale it UP.
Android chooses the one appropriate for the resolution or screen dimensions. ..when it doesn't find one in the right folde than it goes down in the resolution searching for a lower quality folder...again when it doesn't find one in the folder with lower resolutions than it searches in the higher quality....and crashes if there is also none at runtime....AT compiletime you'll get error when thers n no image
Depends on how you display the images....Icons get everytime up or down scaled. ...IT is recommended that you have one and only one xxxhdpi icon in your app because downscaling is better than up scaling due to AA

Trick to supply resources to different drawable folders

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

Reducing Android Alternative Drawable Resources

I have images that need to scale to the screen's size. The images will also have text in it that needs to be translated to a second language. So there will be two versions of each image to start, one for each language.
Google recommends having an image resource per density. So I'd take my two images and multiply them by four: xhdpi, hdpi, mdpi, and ldpi. But then Google say to have different image resource for different screen sizes. This multiplies my images by four again: xlarge, large, normal, and small. I don't want to create 32 copies of every image!
I'm wondering if there is anything wrong with making the images for xlarge screens and xhdpi densities only. IE – Best quality. Let Android scale down the images for lower densities per its standards for dp units. And when I draw on smaller screens, I could use the Canvas class to scale down further. I could cache the resulting scaled Bitmap object for use every time it needs to redraw the bitmap to avoid expensive scaling computations running over and over.
Is there any drawback to doing this? Or is there a better way to avoid making so many copies of the same image?
There will be a performance penalty in downscaling large images on smaller (low-end) devices. Whether this will be noticeable depends on the number of images you have to show.
The same holds, mutatis mutandis, for memory.
I create bitmaps only for the highest xhdpi pixel density, and then test on other screen types.
If a bitmap looks bad on some lower-density screen, I remake it specifically for that density. And this happens quite rarely...
Also, making special bitmaps for different screen sizes (small/xlarge) is not needed - just make your ImageView-s smaller/larger - image scaling is not a slow operation, so in most cases you don't need to worry about it either (unless your bitmaps cover the whole screen).

How do I create good looking drawables.

For my app I need several small icons. I put them at a size of 15dp * 15dp in the layout xml file. The problem is that they do not look good on the device. If I look at the standard android Icons, e.g. for refresh, they look very sharp.
What I did was, I created a 15*15 pixel image with Gimp and tried to use it. I guess that is not a good approach since 15dp != 15 px, right? What is the usual workflow for creating nice, good looking icons, even if they need to be small?
Density-independent pixels (i.e. dip or dp in XML) are designed to provide a more consistent visual appearance across devices by scaling the UI to look roughly the same size on each device. This is not the exact same as physical size scaling, but rather the pixel density (dpi) of the screen. There are basically four buckets any device can fall into (ldpi, mdpi, hdpi, xhdpi). The dp unit is modeled after mdpi, and all other buckets are scale factors from there. In other words, 15dp does equal 15px on an mdpi device, but not on others.
What you need to do for optimum performance is to create your icon in four sizes, and place them in corresponding drawable/ directories. For instance, with your 15dp icon you should have:
A 12x12px image in a res/drawable-ldpi folder (LDPI is 75% of MDPI)
A 15x15px image in a res/drawable-mdpi folder (MDPI is the base)
A 23x23px image in a res/drawable-hdpi folder (HDPI is 150% of MDPI)
A 30x30px image in a res/drawable-xhdpi folder (XHDPI is 200% of MDPI)
The application will grab the proper asset to match the resolution of the device you are running on. If you do not create an asset for each level, the application will take the closest match and scale it up or down (You are probably using an HDPI device to test and your 15px image was getting scaled up to 23px, causing pixelation).
HTH!
According to this page, dp is a unit of scale-independent pixels: 160dp always makes 1 inch on your screen. This should answer your question whether pixel is dp or not: It is only the case with a screen supporting 160dpi. This is a lot more than e.g. the usual PC screens these days (96 dpi).

Categories

Resources