Understanding Density independence - android

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.

Related

Get size of the Android Phone

I would like to get size of the Android Phone but size in mm and not in pixels.
I know how to get size in pixels, however I would like to do some RND and for that I want to get width of the screen in mm.
Like here Galaxy S4 size is Dimensions 136.6 x 69.8 x 7.9 mm (5.38 x 2.75 x 0.31 in)
136.6 x 69.8 x 7.9 mm (5.38 x 2.75 x 0.31 in)
^^^
Does any one knows what is this size for?
Though I am iPhone developer BUT I am beginner (1 day baby) for Android. Well below is what I want to do as RND.
Let's say designer gives me design for the app of size 1080*1920 and have title of size 30px (which covers 80% exactly) of the screen size.
That means 10% space on left side, 80% text and 10% space on right side.
I know in Android we have something called sp or android:textAppearance="#android:style/TextAppearance.Large", but that won't give the 10% spaces.
What I want to achieve is regardless of size, design should go same.
Considering design to fit with width, if height increases, I would have scrollview and I am okay with that.
"Pixel density" is the number of pixels per inch. So dpi gives you the scale factor you need so that the number of pixels is consistent across devices.
Another way of saying this is that if you have a 480 pixel screen with hdpi, then a 360 pixel screen at mdpi is about the same physical size. While the screen sizes may vary some, it generally is not that important. Even so, as mentioned, see this post about doing the actual calculation:
Is there a way to determine android physical screen height in cm or inches?
However, you are talking about percentages of screen size in your example. If you know the screen size in pixels, then the physical size doesn't matter, just do your calculations using pixels. If you have 480 pixels, 10% is 48.
You cannot do this in XML, which it sounds like you might be wanting to do. You can use "weighted linear layouts" for runtime calculations of the screen size. You can also use different res folders depending on screen size (like res/layout-hdpi).
You may want to read this from Google regarding supporting different screen sizes: http://developer.android.com/guide/practices/screens_support.html
Use DisplayMetrics. The API is: http://developer.android.com/reference/android/util/DisplayMetrics.html
You can perform a calculation on the given fields and obtain the height and width in inches, then convert that to mm.

Confusion about Resolution, Screen aspects in Android

I'm asking this question after much reading. I've always heard that dpi is for printers, but when it comes to screen now, they are also talking about dpi. Are they referring to ppi?
Now, what is really resolution, for me its the the number of pixels each dimension can display, e.g. 800x600 means 800 pixesl on width and 600 pixels on the height, but at some places I'm seeing that they are referring to resolution as dpi.
I'm trying to understand this concept well because its very important in Android, like in this article,
For example, say an icon is intended to be 0.5x0.5 in when rendered on a screen. Next, the image must be created at the largest density supported, or as a scalable vector graphic. Best practice is to support the maximum density, which currently is xxhdpi at 480 dpi. At 480 dpi, a 0.5x0.5 in image converts to 240x240 px.
So it is referring dpi as ppi actually if I understand?
So far what I've understood is that different pixels may render different number of pixels. This is why we don't use pixels as measurement unit. Instead we use dp, where a dp is one pixel on 160 dpi device (again the confusion about dpi & ppi)
Can someone clear this big confusion or direct me to an article that may clear it
Mate, Resolution being 800 X 600 implies that the screen has 480,000 pixel points that will be used to render the screen(This is often confused with the dimensions of the display). DPI or PPI means dots/points per inch, this is the measure of the density of the screen.
So just given the Resolution, one can not determine the actual length of the display unless the density parameter is also available. So a 800 X 600 resolution has 480,000 Pixel points & a let this device has a density of 480 dpi.
So the Width of the screen
= No of pixel points along its width/Density
= 800/480
= 1.67 inches
Similarly,
Height = 600/480
=1.25 inches
and if 800X600 resolution device has density of 160 dpi, its dimensions will vary drastically. Following calculations calculate Height/Width of 800X600 on 160 dpi. Compare these two values with above 480 dpi calculations.
the Width of the screen
= No of pixel points along its width/Density
= 800/160
= 5.0 inches
Similarly,
Height = 600/160
=3.75 inches
This is the very reason that scaling images to best fit the screen is such a complex issue on frafmented android environment.However, I love android!
Hope this helps!
and any one who has some thing to add/delete.modify to this answer is most welcome.
dpi (dots per inch) == ppi (pixels per inch)
You are also talking about the DisplayMetrics.density, which gives you the multiplier for the dp unit of measurement.
There's also DisplayMetrics.scaledDensity which also takes into account text size user chose.
To put it plainly, dp unit is intended to give you some security about size of your objects on screen. 160dp should represent one inch on any screen. In order to achieve that, you have to multiply your dimension by DisplayMetrics.density or DisplayMetrics.scaledDensity.
That is, if you're doing that in code. For Layouts, you can just enter a View's dimensions in dp and have Android framework take care of that for you.

Android DPI independence on devices with same the resolution

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.

Calculate pixels based on DPI and Physical Size

I'm trying to make an Evolus Pencil template for Android. My device has a 1.75x2.5625" screen, and I would like to emulate these exact physical dimensions. From reading this post:
Android multiple screen sizes with same density
I see Physical Size = Pixels / Density. So if I create an image that is 168px wide, on a 96dpi screen, should I not get a physical image of 168/96=1.75" wide?
Because I get one about 1.5" and I'm lost. I am running Ubuntu and confirmed my screen dpi with xdpyinfo as being 96x96. So what is a formula I can use for this? I was thinking one could get the pixels needed by multiplying the inches we want on the screen by the dpi of the screen, but this gives me the 168 mentioned above and obviously gets me no where.
Can anyone point me in the right direction, I'm honestly terrible with numbers and math so my apologies if I'm missing something simple or obvious.
Are you sure that the display is actually 96 ppi? Going by the specs, and my own calculations, your Lenovo S10e actually has a density of ~116.36 ppi, which is probably where your difference is coming in.
Assuming these specs are correct:
10.1" diagonal
1024 x 576 resolution
16:9 screen ratio (taken from above resolution)
Using some geometric formulas, you can get the actual width and height of the monitor as:
Width: 8.8"
Height: 4.95"
Dividing 1024/8.8 and 576/4.95 gives you 116.36 pixels per inch, rather than 96.
Using this instead, a 168 pixel image should display as 168/116.36, or ~1.44", which is consistent with your results. I wouldn't put too much faith in the xdpyinfo results. :)

Android multiple screen sizes with same density

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);

Categories

Resources