Canvas get size keep changes with different devices screen size - android

I am trying to draw a circle on Canvas of a View, I am facing a problem that after testing the code on different screen sizes, i found that the drawing size changes although i gave the view a static width and height of 300. I expect it to have same size on all devices.

This is bound to happen because devices have different densities.
Try to use the following to convert to pixels/dpi.
private float dpFromPixels(float px)
{
return px / this.getContext().getResources().getDisplayMetrics().density;
}
private float pixelsFromDp(float dp)
{
return dp * this.getContext().getResources().getDisplayMetrics().density;
}

Density is the number of pixels per square area of the screen. A device with higher density has more pixels in a square inch than a device with a lower density, so your 300x300pixels on an 5inch 1080p device will look a lot smaller than on a 5inch 720p device.

Related

Understanding Density independence

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.

custom view with objects on screens with different screensize and pixel density

I would like to draw a circle in my custom view and it should appear nearly the same size on any screenresolution and density.
for example if I would draw the circle with a radius of 50 pixel, then it appears large on a screen with low resolution. But on a high resolution screen it appears small.
My first try was to simply calculate the size depending on the screensize. BUT on a small device with a very high resolution the circle looks too small.
I guess I can't manage the pixeldensity.
How would you solve my problem ?
regards
You can access screen density via DisplayMetrics as described here How to define a pixel independent height in an onDraw() method

LED Pixel density , LED Pixel height and width , Resolution

Can some one explain me the relation between
LED Pixel density,
LED Pixel height and width , and
Resolution
while creating an emulator
in detailed way..
and again while launching
Default: SkinSize, Density;
Scale density to realsize ?
Pixel density : Pixels per inch (PPI) or pixel density is a measurement of the resolution of devices in various contexts: typically computer displays, image scanners, and digital camera image sensors.
Resolution: or the total number of pixels in a display, is a very important factor that affects the performance of the sign. More resolution means more LED diodes and more circuits, which usually means better picture quality.
Pixel have fixed size height and width, it's just a dot, the no of dots in an inch creates resolution.

Drawing a view on different screen resolution

I am trying to drawing a rectangle view in my application, but its looks different in different devices having different screen resolution. Any idea how to draw same size of view in all different resolution devises. Thanks in advance.
From the documentation (Supporting multiple Screen Sizes):
Multiply your dimensions with scale
// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;

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