I'm programming for a little game in android, but i'm stuck at understanding how the scaling of drawables work or should be done.
I'm drawing a Tilemap in a View on a Canvas with Canvas.drawBitmap()
Main problem is that i don't know how i should manage bitmaps to occupy the same space independent of screen resolution.
My Tile is 64x64 png file and it's placed in drawables folder. Then if i want it to occupy the same space in a xxhdpi screen what should i do?
Should i place in drawables-xxhdpi folder the same tile but as a 192x192 file? Or should i convert px to dps for the drawBitmap() method? Or is there something else?
I'm getting really confused trying out things, and i see myself not getting anywhere.
Thanks in advance!
You're right. You should keep a bitmap file with different resolutions in different drawables folder. That allows the application to fetch the required files automatically on the basis of the size of device the user uses.
Related
I have a beginner question in android. I wanna create a backgammon game. I found images of board online and converted it to different dpi using online tools. Now when I decode it using decodeResource and display it in canvas it's very small. and when I scale it it has very bad quality.I tried all solutions including using matrix for scaling and different paint options. I think the problem is with the image itself. it's 72*72 by default. should I make it larger and then put it into dpi folders?
thanks in advance.
72*72 is very small. You should better make an image in 1920*1080 and put it into the drawable folder so it's not depneding on the size of the screen. You can always scale it down. Maybe make a smaller picture and put it in drawable-small to save ram on smaller devices, since bitmaps are pretty large.
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.
I am wondering what your thoughts are on which is the better strategy when designing UI for android devices.
Which do you preffer:
Setting the size of elements in the XML files, for each denisty (and size when needed), using only one set of images (xxhdpi images) which will scale down when needed.
Pros - smaller apps (less resources)
Less work on images for UI people.
Cons - more work on XML files (a whole lot sometimes)
Create images for each denisty (and size if neede) using Wrap_content most of the time.
Pros - Only one set of XML layout files.
Cons - more images and larger sized apk.
more work on images for UI people.
What other approaches are you using?
Thanks!
I think you are misunderstanding what Android is doing when it scales images that you do not provide. The Android docs state:
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.
All this means is that if you do not provide alternate density versions of images, Android will fill in the missing ones (created and the correct proportional size) using the ones you have provided, but at the cost of some quality of the image, since Android is not going to scale an image as well as say Photoshop. If you are concerned with application size, you can consider if the loss of image quality from omitting certain density versions is an acceptable tradeoff in order to make your .apk smaller.
So, #1 and #2 can both use wrap_content, and neither has to set the size of an image manually, unless the image needs to be larger or smaller than the original size (which in that case you should just create the image at the right size). #1 also does not and should not require more layout work. And for #2, saving an image at several sizes is not very much extra work at all.
I personally follow these rules:
Create images for every density (except ldpi / tvdpi - too few devices, I'm ok with the image quality loss on them).
Use wrap_content and match_parent as needed with images.
Only use dp for images downloaded at runtime, where size cannot be guaranteed.
my choice is a mixed one. I create differet images for those which are complex and has a chance of being abnormal for automatic compression. But for usual images I only used the first approach.
If I put my application resources in drawable-xdpi then it is automatically down converted for hdpi, mdpi and ldpi by ration 0.75, 0.05 and so on.
Why we need to create extra resource if one type is enough only?
I believe it is enough if I create for xhdpi and let Android down scales automatically. I have gone through this question
What is the best way to create drawables for different dpi
but no one has given answer that yes you can go this way.
Suppose I kept my images in xhdpi and when app opens in hdpi it will reduce size to 0.75, when it opens in mdpi it reduces size to 0.5.
So what is best way to create draw able asset? Please suggest perfect way with valid reason.
If not needed why we are creating so many resources instead for one only like xdpi?
There are two reasons to provide more than one image:
it is more efficient to load an image that is already the correct size.
The automatic downscaling may produce artifacts, which can be disturbing especially for small images. So if you want a pixel perfect image it is better to provide one in the correct size.
If none of them is a problem for you, it is also fine to go just with one image.
If u want to display same image with different resolutions in devices
xhdpi image then place it drawable-xhdpi
hdpi image then place it in drawable-hdpi**
or to maintain a drawable folder place all the images what you want to display it will display with same size in all devices irrespective of the resolution.
I am creating an android application in which I want multiple screen support.For these I have used 9 patch images.
But my question is this whether using 9 patch images will be enough for different-2 density's devices or I will need to create different-2 9 patch images for varying densities(like mdpi,ldpi,hdpi).
Thanks in advance
I recently found out myself in the same situation so let me pitch in and expand on what has been said already...
Yes, 9-patch images will scale, that's what they exist for. But if you should use a 9-patch image for all screen densities, that depends on the image really. 9-patch images are more commonly used, for instance, buttons. You can have different sized buttons in your app and a 9-patch image will help deal with them, no matter how you size your button (as long as the 9-patch image is properly created).
But let's say your button design has some really round corners for the hdpi version. You create your 9-patch image without messing the corners but when you look at it in the ldpi version, you'll realize your corners are too big for that low resolution. For this situation, you'll need a different 9-patch image with less round corners, that look better on that resolution.
So, the final answer is, it really depends on your image. If you can create a 9-patch image that looks good in all densities, than fine, use it, as you only need one image to handle all densities. But if it doesn't look good, because of corners, gradients, or whatever, than you'll need one 9-patch image for each screen density.
Hopefully it's clearer now.
From documentation: nine patch
A NinePatchDrawable graphic is a stretchable bitmap image, which Android will automatically resize to accommodate the contents of the View in which you have placed it as the background. An example use of a NinePatch is the backgrounds used by standard Android buttons — buttons must stretch to accommodate strings of various lengths. A NinePatch drawable is a standard PNG image that includes an extra 1-pixel-wide border. It must be saved with the extension .9.png, and saved into the res/drawable/ directory of your project.
the answer is no. you nine patch will scale between different screen size
Short answer is YES.
Check this:
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.
from Android Developer Official Doc