Very much a newbie question here but I cannot find a clear answer on the net or in the books I have. I am designing an app to be compatible with all sizes of android devices and I want to display a images in my app. I understand that android automatically scales images to suit the resolution of the screen being displayed.
My question is what do I look for in the images I use? E.g. I have a picture that's 2418 x 2192 # 240dpi. As far as I can tell, this should be perfect for a larger screen such as a tablet. If I put this into the xhdpi image folder in my project will it be detected by other devices and scaled to suit their dimensions/resolutions? Do I have to create 3 different versions of this image in photoshop and put it into the relevant dpi folders?
I can't find a nice beginners tutorial for this stuff so haven't a clue what I'm doing!
This is the best place to start for multiple screen size support:
http://developer.android.com/guide/practices/screens_support.html
The short answer is, yes, you place the images in the different directories based on resolution and Android will select which image to use based on the device's properties. You should make a smaller set of images, for example, for mdpi and hdpi. You don't "have to" do that, and if you just place the image into drawable it can be scaled down, but that's generally not the best way to go.
This is something you'll deal with on just about all project, because there simply are so many Android devices. This resource has helped me greatly.
If you have a resource in only ONE folder, Android will scale it for you. The different drawable folders are intended to allow the developer to provide properly scaled images with minimal effort. For example, you'll want to provide an xhdpi in addition to the "standard" mdpi image to make assets look better on high-resolution devices. The app would work fine (and have scaled images) in all resolutions, even if you provided only a single image. However, if you provided a xhdpi drawable, then there's a bit of overhead to scale all of those down, and especially for icons, the results may not look very good (or even be recognizable).
I generally provide assets for mdpi and xhdpi, but if the app will see frequent use on low-res devices, I provide the ldpi as well. If possible, I include all four.
Note: The image you mention is much too large to be included in the UI resources and would probably best be placed in assets and loaded on request. Even on xhdpi devices, it would have to be scaled down.
Related
Until now, I did not pay too much attention to how to store drawable resources.
I usually generate multiple versions of an icon and store them under the drawable-mdpi, drawable-hdpi, drawable-xhdpi, ... folders.
For other images for which I don't have multiple versions, I inconsistently store them under drawable-nodpi or drawable.
However, I recently encountered an issue related that bring all my attention to that. I stored a 100KB image under the drawable folder. However, my app was regularly crashing, stating it could not allocate 18MB!
After some searches, the reason was that the image was scaled to fit the screen resolution and it resulted in a way heavier image. The fix was to move it under the drawable-nodpi folder which prevents that scaling.
So now, I am trying to better understand where I should locate my images and how this scaling effect works to optimize my app on that part.
I have done plenty of searches, but resources are limited or unclear on that subject and the official documentation kinda really sucks.
I am aware of the official explanation for the drawable or drawable-nodpi, but it does not clarify everything.
Typically:
How does the scaling work? Let's say I have res/drawable-mdpi/image.png. Does that mean the image is scaled if I have a screen different from mdpi, or will it also be scaled on mdpi screens resulting in possibly heavier image size on every device?
Following previous question, if the image is not scaled for mdpi screens but scaled for any others, then does that mean that if I provide a version of this image for every screen density, the scale will never happen? Or at the opposite, if the image is scaled also on mdpi devices, then having different version of the same image for each screen density will still scale the image, but using the version of the image matching the screen density of the device?
How to deal with icons for which I do not have multiple versions? I am afraid that if I put this single version in mdpi, it just scales it and uses so much more memory than necessary. In such case, should I put any icon for which I do not have different versions under nodpi?
On the other hand, if whenever you put an image in mdpi, hdpi, ... it scales it even on devices matching the density, then should I just move everything under nodpi or some high resolution like xxxhdpi where it can only be downscaled?
Thanks
Let's say I have res/drawable-mdpi/image.png. Does that mean the image is scaled if I have a screen different from mdpi
Yes.
or will it also be scaled on mdpi screens resulting in possibly heavier image size on every device?
No.
if I provide a version of this image for every screen density, the scale will never happen?
Yes. Your APK will be larger, due to the 7 copies of the drawable.
How to deal with icons for which I do not have multiple versions?
Option #1: Decide what density that particular version belongs in, and put it there. Android will upsample or downsample the image for devices operating at other densities.
Option #2: Put it in -anydpi or -nodpi, in which case Android will not upsample or downsample it. However, in this case, you need to be controlling the size of the image yourself (e.g., in the ImageView).
Option #3: Replace the icon with one that either you have all relevant densities or one that is an SVG that works as a vector drawable when imported using the Vector Asset Wizard in Android Studio.
The decision-making needs to be based both on memory consumption and what the result looks like. A low-memory solution that looks awful is unlikely to be a good choice.
should I just move everything under nodpi
Probably not.
or some high resolution like xxxhdpi where it can only be downscaled?
Probably not. It is unlikely that a massively downscaled version of your icon will look very good.
I saw many questions like these and read many docs, but I'm still not sure what is the proper way. I have application with 500 photos, and first how I was doing it was to scale every photo 5 times, to the pixel sizes for each ldpi, mdpi, hdpi, xhdpi and xxhdpi. But, after doing this, application got much bigger than it should have and since you can only upload .apk with 50MB to market, I found myself in trap.
I found several options which can be made here, but not sure which is the proper one:
Make a multiple layouts for each of this densities on devices and scale with different dp's in them
Make multiple .apk files, each for every device with different densities (still, Google is making accent on this option to make it only if you really can't make it anyhow else - why is that? this would be perfect for me, since I already have photos prepared for each density)
Make multiple pictures and put it just in one .apk - this can't work for me, since the .apk is too big
Make pictures which are good for MDPI device, put them in "drawable" and they will automatically resize bigger for other devices and smaller for smaller density devices - this makes problem since pictures, when they're being resized from MDPI to other bigger dpi devices, pictures are blurry.
So, anyways, proper way of handling this would be to follow first option, am I right? I should just take xxhdpi pictures (so they're always scaled from the best picture), put them into drawable-nodpi? However, I have some problems with scaling on ImageButtons.
Please, tell me how to make it properly.
My practice is using only one apk to keep the app simple and easy to develop and publish.
Use only one drawable, the high the better. it depends the final apk size you(market) can bear.
May be this question will help:
Only use XHDPI drawables in Android app?
An addition to the Loki's answer. You could resolve the poor perfomance on small scale devices making a cache folder for images. Downsize the image the first time the device loads it, according to the density of the device, save it to the cache folder, and the next time use the cached image.
Bonus if you make this in an batch process in the background!
I don't know but could this be done as an update to the app. You download a plain vanilla app that prompts the user to upgrade, or just does it automatically.sounds like something Google needs to improve on. When I download an app I only need one app for one language one device.sounds like Microsoft mentality
I'm quite new to Android development. My understanding is that you can create several versions of the same image with different sizes and put them into the folders drawable-ldpi, drawable-mdpi, drawable-hdpi.
It seems obvious to me that you can handle this problem "the lazy way" by just resizing one image depending on the device's pixel density. For this I programmatically find out what density the device has, like ldpi. The implementation itself is not the problem. I'm just afraid of any drawbacks (that prevent me later from running the app on different devices).
So, are there any (major) drawbacks of scaling images automatically ?
In which of the three folders do I put the image so that the compiler can find it?
You would put the image in your regular drawable folder. That way any phone can find it.
While you can programatically shrink images, shrinking usually has the effect of reducing image detail and causing jaggies.
Adding in smaller assets will also reduce memory usage on smaller phones. Keep in mind that some Android phones are notoriously bad with memory (see: HTC Status), so any and all savings help.
I would recommend just photoshop scaling images down large images yourself. For smaller images, it is not as big a deal.
Android does auto-scale and it works fine in some cases, but it doesn't work for many, notably small images with important details like text. Scaling a larger image down blurs those details. Scaling a smaller image up is worse. This is why icons files have been multi-resolution since the very early days of GUIs. To wit, text scaling is hugely complicated. Ask any font designer, and note Adobe built a company on algorithms to do it automatically.
it's on mdpi folder. It'll change the size automatically. But is not recommended since the image quality drops.
I've been through this post (and others) as well as through the documentation about supporting different screen resolutions in Android, but I couldn't find a clear answer to a (simple) question:
Is it ok to just use "res/drawable" for images in an android app?
Background: The only images that are needed in this specific app are the app icon itself and an icon for a notification, there won't be any images in any layout.So in my understanding, if no "hdpi"-, "mdpi"- and "ldpi"-folders are found, Android will use "res/drawable" as the fallback.As the only pitfall with different screen-resolution seems to be that Android will scale images for a specific resolution if no special one is found, this should only be a problem when UPscaling, because the image will get blurry. But if I provide all "hdpi"-images in "res/drawable" (instead of 3 different ones), won't Android just DOWNscale those images if the size is too big?If that's true, I could save some APK-space by just a third of the images.
Follow-Up question: I read that for API-level 3 a dir by the name "drawable-v3" is required. Is that true or is "drawable" the fallback for this API-level also?
Any hint is appreciated.
The images in the drawables folder are assumed to be at mdpi resolution, so they will get scaled up/down if you don't provide the others.
Scaled up images will be low-resolution and look fuzzy. Scaled down images will have pixels missing and look jaggy.
So your app will "work" with only one set of default images, but will look awful on many devices. I strongly advise that you create the images in different sizes, so it looks great on all devices - it's a bit boring, but not hard to do.
It won't be long before we have xhdpi devices, so while you're at it you may want to create those too.
I assume you've read this
Not a complete answer, but: highly downscaled images can and usually do look just as bad as upscaled images (but in a different way), because graphics libraries almost exclusively use interpolation methods for resizing, and interpolation methods are limited in terms of how much they can shrink an image before serious information loss (to about 50% for linear methods and down to about 25% for bicubic methods). This is why most platforms have evolved conventions (like hdpi, mdpi etc.) that let you embed images that are best for each screen size.
I use drawable/ all the time, and then I go to BestBuy and all the local wireless stores and test my apps on small/large/huge(tablet) devices and they look just fine.
Unless you have some reason to target pre-Donut devices (now only 4% of the devices according to http://developer.android.com/resources/dashboard/platform-versions.html), then you should put your bitmaps in one of the -Xdpi directories. The generic "drawable" directory is a synonym of "drawable-mdpi" for compatibility reasons, but a modern well-written app should be putting its drawables in a directory matching the density they are designed for.
res/drawable is the fallback
the caveat is that scaling not only degrades the image but takes processing time too.
I have not even read the API-Level 3 docs yet, sorry for 1/2 an answer
For what it is worth I found the image handling of Android to be tedious and unreliable. The concept of including different size images for different screens will result in large application files bloated with images. There are already screens that don't fit in the standard resolution ranges. I have found it is best not to let android handle the scaling, it seems to create a base image for the smallest screen you target and then scale it up resulting in ordinary looking images on large screens. This happens even if you made the image specifically for the large screen.
My solution that seems to work on everything from a 2" samsung phone to a Sony Tablet is to create images at high resolution and use Bitmap.createScaledBitmap() to get the size I need.
caveat: I am new to Android and have lots to learn.
I was wondering if there is a way for using one set of images for all the resolutions. I have an application, and I want to port it on all the android resolutions but I don't want to store 3 sets of images, for every resolution category. What would be the best practice to use as less images as possible.
Thank you!
Sure, you can provide only one set of images, in the base drawable directory, and Android will automatically resize as required.
This may result in aliasing and images that are not as clear as would be possible if you were to provide images sized properly.
You probably mean density, not resolution (in Android, applications do not work directly with resolution).
Actually, you don't need to support all 3 densities. Quote from developer.android.com:
This pre-scaling mechanism works independently of the source. For instance, an application targeted for a high-density screen may have bitmaps only in the res/drawable-hdpi/ directory. If one of the bitmaps is a 240x240 icon and is loaded on a medium-density screen, the resulting bitmap will measure 160x160.
I've done simple test: removed ldpi and mdpi density images, launched my app on mdpi skin and it scaled hdpi images nicely. It's not the best practice, but android's prescaling does its part as described.
Please read this for more details.
I wrote a tool which makes this all a lot easier to manage. Although the images are stored in separate directories - the tool shows all resolutions together, and lets you auto-scale from one to another.
you can get it here: http://hobbyistsoftware.com/AndroidImageViewer