2

I have a major issue I am working on for days now. It is much understandable by looking at the requirement first. I will list down my requirement as simple as possible in point form below.

  1. I have 5 android phones. 5 different brands, different screen sizes.
  2. Imagine the screen sizes are 4inch, 4.5inch, 5inch, 5.1inch and 5.2inch
  3. I have an android app and it has a drawing canvas.
  4. Now using canvas.drawCircle(x / 2, y / 2, radius, paint) I am drawing a circle. Imagine the radius is 100 (100 pixels?)
  5. I install this app in my smallest screen phone, 4inch. Then I use a ruler and measure the the circle diameter. Imagine the circle diameter is "exact" 3cm.
  6. Now I install this in my other phones.
  7. Unfortunately, in my 4.5 inch phone the circle diameter is 3.2cm. In 5 inch phone it is 3.3 cm. In 5.1 inch phone it is 2.8cm and so on.
  8. However I want my circle diameter to be 3cm (exact 3cm) in every phone.

Above requirement is something I am trying for days now. I tried the following to make sure I get a circle with no size change across all screens.

  1. Using ImageView - I tried using an ImageView and added a circle image. I have given the width, height fixed. I have tryied setting the values in px, dp, inches etc. I also tried scalling options available for ImageView. Also tried placing the same image in drawable-nodpi folder. Tried creating drawable folders for all sizes (ex: drawable-mdpi, drawable-hdpi). Non of this stopped the image from being scaled.
  2. Using Canvas - As explained in the above, I tried using canvas and drawing the image. The drawing scales.
  3. Finding pixels per inch.- Tried finding pixels per inch of each phone programatically thinking I can find a way to develop a logic from it to dynamically draw the images in same size. I used several links including - Calculate PPI of Android Device. Most of them talk about getting screen resolution only.

How can I fulfill my requirement of drawing same size circles? If it can be done by knowing PPI, how should I do it?

Community
  • 1
  • 1
PeakGen
  • 21,894
  • 86
  • 261
  • 463

2 Answers2

1

The Answer before has worked for me but as long as it didn't for you I will try explain something I think it will help.

I have a device that have a density of 1 (160 px per inch), and the Display metrics told me that i have 320 * 480 pixels, with simple calculation I should know my mobile width and height in inch like this : 320 /160 = 2 inch for width , 480/160 = 3 . for now everything was just fine until i got the ruler and measured it and the surprise was this : I have a 1.65 * 2.48 inch !!.

Then I noticed that there is something called physical pixels per inch of the screen this was the relief for me and you can get it like this :

getResources().getDisplayMetrics().xdpi;  //for width physical dpi
getResources().getDisplayMetrics().ydpi;  //for height physical dpi

And now I can calculate my Physical width and height of my device like this :

my physical dpi for both width and height is 193.5238 so...

320 / 193.5238 = 1.65 inch width 480 / 193.5238 = 2.48 inch height

And that was correct !!.

Now back to your problem lets get the 3cm in pixels for any Phone :

getting the width in cm :

width in cm = width in inch * 2.54 (because 1 inch equals 2.54 cm)

getting the amount of pixels in each cm :

width in pixels / width in cm = Pixels per cm for width (px/cm)

now you want a 3cm then the pixels according to it is:

3 * Number = 3cm Pixels

all of the above can be shortened like this :

float devicePixelsWidth = getResources().getDisplayMetrics().widthPixels;
float deviceActualDpi = getResources().getDisplayMetrics().xdpi ;
float deviceActualInchWidth = devicePixelsWidth / deviceActualDpi ;
float deviceActualCMWidth = deviceActualInchWidth * 2.54f ;

float PixelsForActual3CM = devicePixelsWidth / deviceActualCMWidth * 3;

In the end, all of the above has been tested and approved by me and has the same accuracy of the previous Answer method :)

Omar
  • 458
  • 2
  • 10
0

maybe this is not answer, but might be helpful

float _100MmAsPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM,
    100/*mm unit set*/, getResources().getDisplayMetrics());

above gives me 1661.5354 on Nexus 5x and 1889.7638 Nexus 5 (emulator). both have fullHD display, but 5 has 4.95 inch versus 5.2 inch in 5x.

it means 100 millimeters is 1662 pixels on 6 and 1890 on 5x

snachmsm
  • 17,866
  • 3
  • 32
  • 74
  • its changing integer with number of `COMPLEX_UNIT_MM` (millimeters) to pixles (always). – snachmsm May 06 '16 at 08:14
  • I mean is it pixels per inch? – PeakGen May 06 '16 at 08:14
  • So to use this, i will actually require the width, not the length, because I will vbe drawing a circle and diameter comes in width. – PeakGen May 06 '16 at 08:21
  • you need proper radius in pixels for drawing on `Canvas`. `float _30MmAsPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 30, getResources().getDisplayMetrics());` gives you 30 mm in pixels unit depending on device density/size/resolution. Just use `_30MmAsPx/2` as radius. Now you are giving fixed 100 pixels for radius (assumed) and this might be slighty different on devices with same resolution, but different screen size. Above line calculates proper px values from given mm – snachmsm May 06 '16 at 08:34
  • I tried by giving 20mm. When the circle is drawn based on the value generated, the diameter was 3.3CM ! – PeakGen May 06 '16 at 08:54
  • so my ans isn't proper :( BUT I've checked my sample with 100 mm as px on physical device with a ruler and it seems to work... – snachmsm May 06 '16 at 09:06