I Have a few general questions about Android screen / DPI / resolution indepence.
Basically, I am taking specifically about sprite-based apps, like ones based on Surfaceview for example.
Every guide I've read (including the official one) says that you should only work with the DPI and not the resolution.
However, what happens when two devices have different DPI's/screen size but the same resolution? Take the Galaxy tab 10.1 (1280 x 800 - DPI aprox 150) and the Galaxy Note (1280 x 800 aprox 285 DPI I think??)
When displaying a sprite of say 50 x 50 on each of these, it will appear to be the same size relative to the screen size. However, if Android grabs a difference size sprite because it detects a different DPI (ie, from LDPI, HDPI etc), then the sprite will appear to be bigger on the Note relative to the screen size than it would on the Tab.
Can anyone please set me straight on this as I just cannot work it out!! Thanks all.
A 50 x 50 sprite on a 150dpi screen will appear much larger than a 50 x 50 sprite on a 285dpi screen. Android's resource resolution algorithm is intended to allow you to define a larger (in pixels) image for use on higher density screens.
If you want the sprite to be the same size relative to the screen regardless of the pixel density, then you can put the images in the drawable-nodpi folder and they won't be scaled by the system. You can even decide which size image to use in code after querying the screen size. (As of 3.2, you can have resource folders that depend on screen pixel size, but I think they will still scale with dpi.)
Screen resolution refers to the screen dimension in pixels. Pixel density refers to how many pixels it takes to fill an inch of screen.
Related
I'm making an android App that shows images at full screen.
I learned some about dpi and dp, but I didn't find how many pixel must be the largest side of my images (in prospective to good fit also in landscape mode) to appear good in different devices.
As in the documentation, the most used screen configurations are normal with hdpi, xhdpi and xxhdpi density:
So, if my thinking is correct, I can make only one image to fit the xxhdpi to works fine also with the other two densities, and put it in Android Studio under the "res/drawable" folder (without qualifier).
Specifying the image size in dp in the layout, Android should scale the image for the smaller configurations.
But, for the xxhdpi, how many pixel must be the largest side of my image, in pixel, to show good?
Edit: how many pixel must be the longest side of my image to be showed properly in a device with xxhdpi density without the image appearing grainy?
All images are photo, not icons, so I can't use the vector graphics.
By looking at the Android Documentation. One can estimate the size of the picture. look at below picture
So, your image resolution should be in similar resolution
LDPI: 200 X 320px
MDPI: 320 X 480px
HDPI: 480 X 800px
XHDPI: 720 X 1280px
XXHDPI: 960 X 1600px
XXXHDPI: 1440 x 2560px
A little bit of +/- won't affect the outcome because with these standard sizes the aspect ratio of any portrait picture should be respected.
Well, if you put the image which fits the xxxhdpi inside the folder drawable, then it will fit all the screens.
But there is another way to use only one image instead of using multiple images for different resolutions. It's by using svg images which are vector images that will not be affected by zoom in or zoom out.
To use svg you need to follow these instructions:
Make the icon to be icon.svg
In the Android Studio, right click on drawable folder
Choose New -> Vector Asset
Choose Local File (SVG, PSD)
Choose your svg file
Click Next and choose the name
Click Finish
In the app build.gradle add the following inside android block:
vectorDrawables {
useSupportLibrary true
}
In the xml layout file, add the following:
<AppCompatImageView
android:width="wrap_content"
android:height="wrap_content"
app:srcCompat="#drawable/your_svg_file"
/>
Android have ratios defined for a image to set in all different drawables
Android icons require five separate sizes for different screen pixel densities. Icons for lower resolution are created automatically from the baseline.
mdpi: 160 dpi 1×
hdpi: 240 dpi 1.5×
xhdpi: 320 dpi 2×
xxhdpi: 480 dpi 3×
xxxhdpi:640 dpi 4×
Above size is for normal pixel icons. There are fix android size for Action bar, Dialog & Tab icons, Launcher icons & Notification icons
Check this link for more details http://iconhandbook.co.uk/reference/chart/android/
You have to take a look at the current market of smartphones.
Here you can see the screen sizes and resolutions of the most popular devices in the market.
http://screensiz.es/
Order the list in pixel per inch and you will see that top smartphones have resolutions bigger than 500 ppi or another way to see it, much bigger than 72ppi of your images.
If you have enough space to store or mechanism to download images try to test with full quality. If thats too much try to find a compromise. Lower image quality and see the result in high resolution screen.
Note that you didn't posted here the total size of image, in case is bigger than screen size, take a look at total size of image and compress it to fit your needs, maintaining as much as possible the resolution.
Edit: Looking only to size of image in pixels, the current biggest screen in smartphone is 2560 x 1440 pixels, so you wont need any image bigger than this.
If I understand your answer correctly, you are talking about images (pictures of lovely cats and dogs?) and not about icons?
I prefer putting images into the nodpi folder.
nodpi Resources for all densities. These are density-independent
resources. The system does not scale resources tagged with this
qualifier, regardless of the current screen's density.
Afterwards I would create a fullscreen ImageView and let imageView do the scaling if needed
I need help understanding the subject. I tried many times to develop something in Android and every single time i get stuck at this.
Currently i have two virtual devices:
480x800 mdpi
480x800 hdpi
Now in my view with a canvas i want to draw a rectangle with
canvas.drawRect(0, 0, 100, 100);
So the results are:
mdpi rect of 100px (size measured with gimp).
hdpi rect of 88px (size measured with gimp).
So my question is, if i want to make this rectangle move and control collisions with screen limits how i can get the scale factor that has been applied from density, how i get that the final size of my rect is 88px instead of 100px?
EXTENSION: From this point is it possible that in both devices the rect size will be 100px? What is the formula to achieve this?
Actually, the rectangle is exactly 100px wide on both devices. What you actually measured was the physical width of the rectangle.
Confused? Let me explain:
The rectangle gets drawn as exactly 100px wide on both devices. They have the same screen resolution, but one has a lower density, measured in dpi (= dots per inch) or sometimes ppi (= pixels per inch). (In Android, as you might already know mdpi means medium dpi (~160dpi) and hdpi means high dpi (~240dpi))
Now, dpi is nothing else than the physical size of one pixel, instead of saying there are 160 pixels/inch you could also say one pixel is 0.something inches big.
That means the physical size of the rect you draw is the width of the rectsize of one pixel. Also, the width of the screen is the resolution in pxsize of one pixel. (Actually, the screen of the mdpi device should be displayed smaller than the hpdi device's one)
What happens is that the emulator takes your monitors dpi into account and scales the device accordingly. For your mdpi device it just works out that one device pixel is translated to one monitor pixel, for the hdpi device one device pixel is equal to 0.88 monitor pixels.
In other words, the if these were real phones, the mdpi would have a bigger screen allthough both have the same resolution. The rect would be 100px wide on both but since a pixel on the mdpi phone is bigger the rect would be physically bigger. The pixels on your monitor thus actually are the physical size of the rect.
If you still have no idea what i'm talking about, read this article about supporting different screens in android.
Ok so I know questions about resources for different densities have already been asked, however I ran into a problem, which is why this question is different. Ok so on the android developers website here http://developer.android.com/training/multiscreen/screendensities.html it's stated to use the scale of 1.0 for mdpi, 1.5 for hdpi, 2.0 for xhpdi, and so forth. But the problem is this scale appears to be wrong. If I make an image that is 480x800 for the nexus 1, it will take up the entire screen. If I divide this by 1.5 to get the mdpi version which is the baseline, I will get 320x533.34 approximately. Now lets try multiplying this by 2.0 to get xhdpi version. You will get 640x1066.68. In other words, on a nexus 4 with xdpi and resolution of 768x1280, the image will NOT take up the whole screen. The scaling is not accurate. So I made an image that takes up the whole screen of the nexus 1, then scaled it according the the scale given by the android developers, and for other screens the image will not take up the whole screen. I want a scale that will give me complete accuracy. Thanks!
In other words, on a nexus 4 with xdpi and resolution of 768x1280, the image will NOT take up the whole screen
It is not supposed to. Density has nothing to do with screen size. I can have an -xhdpi screen that is one inch, one foot, one meter, one mile, or one parsec in diagonal length. Those screens would have drastically different resolutions, but the density would be the same.
MDPI is 1.0 as you said, not 1.5. If you create an image that is 480x800 in the MDPI folder, it will be scaled up to 720x1200 on an HDPI device, or 960x1600 on an XHDPI device. You're never going to get an image which properly fits all screens -- there are just too many aspect ratios and resolutions to do that properly. Try to avoid that design philosophy altogether if possible (e.g. maybe have a nine-patch image in the center with a stretchable region on the edges), or set the image to scale and crop to fit (e.g. scaleType="centerCrop") and keep important parts of the image away from the sides of the screen to allow for some wiggle room.
I have an android app that I'm trying to add support for different densities, screen sizes, etc. I've developed the app on the simulator with the HVGA support and used all icons from our iphone app which turns out nice since the resolution was at 320x480. Everything looks good now but I'm a bit confused after reading the official android documentation. For layouts I'm going through and ensuring everything is in dp units but when it comes to the images I'm lost. I know that mdpi is 160 but what do I tell my designer for what the hdpi image needs to be? Do we need to increase the height and width and the dpi? Or is it simply enough to leave the dpi as is and increase the height width? For example, if I have an image that's 100 x 100 with 160 dpi, in order to render it identical on an hdpi screen it should now be 150 x 150 with 240 dpi? Assuming if I leave the dpi at 160 it will just be a little blurred? Sorry about silly question but I just want to make sure I'm doing everything right and I'm really a C developer with no graphics experience at all.... No excuse at all but could use some help. I saw some examples where the splash screen for mdpi was 320x480 at 160 dpi but then the hdpi splash screen was at 480 x 800 at 240. Obviously 480 x 1.5 does not equal 800. Furthermore, after looking at the icons in the android sdk, they only scale up the width and height, not the dpi. Probably because they're icons and don't need to be? Lost in photoshop land....
For me as a Graphic Artist of a Mobile Development Company, I made UI's for Android in this dimension:
HDPI : 640px x 960px in 300dpi optimized by 75%
MDPI : 640px x 960px in 300dpi optimized by 50%
LDPI : 640px x 960px in 300dpi optimized by 25%
Take a look at Providing Resources.
There is a section there on "Screen pixel density (dpi)". You are correct that you just scale your width and height for the resources. A 90 pixel image at ldpi becomes a 120 px a mdpi, a 180 at hdpi and a 240 ad xhdpi.
You are also right that the 800 isn't 1.5 x the base 480 height. The reason for that is that these are all approximates based on targets for each density. The phone os lies to the applications running on it about its actual height and width and scales the resources to match the exact dimensions of the handset, since it can vary. This is my understanding.
I recently solved this problem by generating many PNGs of different sizes from a SVG vector image. These are the ratios I used for screen pixel densities and screen sizes:
ldpi:mdpi:hdpi:xhdpi:xxhdpi <-> 3:4:6:8:12
sw320dp:sw360dp:sw480d:sw600dp:sw720dp <-> 8:9:12:15:18
Putting these two together can give a 5 by 5 table of image size ratios that you need in make your image resources look great on most Android devices' screens. Of course, the downside is that many images will be generated, and the size of your APK will grow.
Please see http://aleakymemory.blogspot.com/2013/11/a-different-look-at-managing-android.html for the table of image size ratios.
Everything looks good now but I'm a bit confused after reading the official android documentation.
Which documentation did you read? Here are some to be going on with:
Supporting Multiple Screens
Icon Design
I'm confused regarding the densities. I see that with medium density, the screen resolution could be either 320x480, 480x800, or 480x854. So if I have an image thats 300px wide in the mdpi folder, how is it going to look the same size on all 3 different screen sizes (mainly 320x480 vs the other 2)?
And by look the same size, I mean scale to be bigger or smaller depending upon the screen size. Thanks.
There are three distinct but linked concepts to understand here: screen density (pixels per inch/centimeter, or commonly known as DPI from dots per inch in printers), physical screen size (in inches or centimeters) and number of pixels (also known as resolution, in pixels).
These terms are not interchangeable, and you need to understand how they interlink to not be confused with the issue. Generally, you can ignore physical screen size since that's already accounted for in the density. For example a screen 3 inches wide and 300 pixels across will have a DPI of 100. Furthermore phones screens tend to have about the same physical size, even if the number of pixels is very different.
So, let's consider the screen of a G1 or Hero which has a resolution 480x320 and a density of approx 160dpi. An image 300 pixels wide will be 1.875 inches across. This is calculated by pixel size (300) / density (160). Now if you compare this to the screen of the Nexus One, Droid or similar, these models have a higher resolution screen of approx 800x480 with a high density of approx 240dpi. If you display the same 300px wide image, it will now only physically be displayed at about one and a quarter inches across. In other words, it will be much smaller. This can be a problem because if the image contains text, then the text might not be readable anymore.
Android can be told to automatically scale images to fit these different screens so that it still looks to be the same size. This is done by setting sizes in Density Independent pixels. If something is 100dp wide, it will be 100px wide on a medium density screen. On a high density screen, it will be 150px wide, but they will both look about the same size on the actual screen. However, if you do this, your image can go a bit blurry. It's the same as when you zoom into a photo too closely in a picture viewing program; the edges go blurry since it 'stretches' them while you zoom.
The way to solve this is to use the mdpi, hdpi and so forth folders. You're giving Android an image that has already been scaled, so that it doesn't have to do it itself. Obviously if you just stretch the image yourself in Photoshop, then it won't look any better. But normally one is resizing very large images down to make them fit the mobile screen. In that case, you just resize them three different times, each into a different resolution.
So to finally answer your specific question: if you have an image placed in your mdpi folder, it will be exactly the same size regardless of the screen resolution, as long as they are all the same density. What will change is how much space around them, e.g. a 320x320px wide image would fill most of a 320x480 screen, but only about a third of a 480x800 screen. However, as noted above, generally the higher resolution phones also have a more dense screen. In that case, Android won't look in your mdpi folder for the image - it will go to the hdpi folder, and if it can't find it there, it will take the default "drawable" folder. Then if you've used DP it will automatically scale it, or if you've used PX, it will leave it as is, and it will just look smaller.
There! A very long answer for you. I hope it makes sense.
For completeness, also check these option for controlling layout:
Directory qualifiers:
Size: small, normal, large
Density: ldpi, mdpi, hdpi, nodpi(no auto-scale)
Aspect ratio: long, notlong
Orientation: land
Usage:
res/layout/my_layout.xml
res/layout-small/my_layout.xml
res/layout-large/my_layout.xml
res/layout-large-long/my_layout.xml
res/layout-large-land/my_layout.xml
res/drawable-ldpi/my_icon.png
res/drawable-mdpi/dpi/my_icon.png
res/drawable-hdpi/my_icon.png
res/drawable-nodpi/composite.xml
Restricting your app to specific screen sizes(via the AndroidManifest):
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
...
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:smallScreens="true"
android:anyDensity="true" />
...
</manifest>
And for code level tweeking:
float scale = getContext().getResources().getDisplayMetrics().density;
And don't forget:
dpi = 160; //At 160dpi
pixels = dips * (density / dpi)
It's all in this doc:
developer.android.com:Supporting Multiple Screens
So if I have an image thats 300px wide
in the mdpi folder, how is it going to
look the same size on all 3 different
screen sizes (mainly 320x480 vs the
other 2)?
How the image looks, physically, is driven by screen density, not screen size. Your -mdpi folder is not tied to screen size -- it is tied to screen density.
This is what Device Independent Pixels (DIPs) are for. Instead of 320px write 320dip.
http://developer.android.com/guide/practices/screens_support.html
Could you please confirm the formula for calculating the screen density?
As I have read, the following is the formula:
Density = SQRT (wp^2 + hp^2)/screen size
wp -> width of the screen (in px)
hp -> height of the screen (in px)
screen size -> Physical screen size (diagonal inches)
screen size (320x480) = SQRT(102400 + 230400) /160 = 3.6 inches
screen size (480x800) = SQRT(640000 + 230400) /160 = 5.8 inches
screen size (480x854) = SQRT(729316 + 230400) /160 = 6.12 inches
So, the layouts (UI screens) are driven by screen sizes (small: <3", normal <4",
large >5") and drawable resources (images) are driven by screen densities.
And, the size of the image (in pixels) does not change if the density of the screens
(320x480, 480x800, or 480x854) are the same.
Could you please confirm?
Thanks,
Ram
Actually the code to calculate physical screen size for devices is the following one:
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
double x = Math.pow(dm.widthPixels/dm.xdpi,2);
double y = Math.pow(dm.heightPixels/dm.ydpi,2);
double screenInches = Math.sqrt(x+y);