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.
I have 5 android phones. 5 different brands, different screen sizes.
Imagine the screen sizes are 4inch, 4.5inch, 5inch, 5.1inch and 5.2inch
I have an android app and it has a drawing canvas.
Now using canvas.drawCircle(x / 2, y / 2, radius, paint) I am drawing a circle. Imagine the radius is 100 (100 pixels?)
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.
Now I install this in my other phones.
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.
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.
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.
Using Canvas - As explained in the above, I tried using canvas and drawing the image. The drawing scales.
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?
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 :)
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
Related
So I'm implementing admob banners into my Unity 4.6 Android game. I have the banner at the bottom and need to account for it in my UI. Specifically I need to know exactly how tall it is, but I'm having trouble with figuring this out.
Based on the information found here the Smart Banner should be 32, 50, or 90 pixels tall, depending on device height. This doesn't seem to typically be the case though.
Some searching would seem to indicate this is because of density pixels. So I attempt to convert the stated pixel height using px = dp * (Screen.dpi/ 160). So for example if I determine the banner height should be 90 pixels, I would use bannerHeight = 90 * (Screen.dpi / 160). This seems to work on some devices but not others.
For example my Nexus 4 has a DPI of 320. Using the above it would seem to indicate that the banner should be 180 pixels tall, but the banner appears to actually be about 90 pixels tall. But on the Nexus 7 (which has a dpi of 166), the banner appears to be about 120 pixels tall when the formula would indicate it should be ~93.
So I guess I have no idea how to figure out how tall the banner is actually going to be, and I haven't found a way to get this information from the API. My code for calling the banner is pretty stock:
string adUnitId = "my_id";
BannerView bannerView = new BannerView(adUnitId, AdSize.SmartBanner, AdPosition.Bottom);
AdRequest request = new AdRequest.Builder().Build();
bannerView.LoadAd(request);
First you need to calculate which Ads google will give you (32 or 50 or 90 ?)
for this you can calculate it by screen sizes.
height/dpi = actual height in inches
so, Google says above 720 (with dp of 160dpi) is acctauly
720/160 = 4.5 inch height, above this height, the ads are 90 pixels (dp!)
below its 50 dp!
400/160 = 2.5 , below this, ads will be 32 dp
SO!
if i have Xiaomi mi3 with 1920x1080
thats,
1920/480dpi = 4 inch height..which will give us 50 dp ads.
with the formula of converting DP to pixel
px = dp * (Screen.dpi/ 160)
50 * (480/160) = 150 pixels height for the ad!
For landscape you need to use as "height" 1080 instead of 1920
1080/480dpi = 2.25 height in landscape
this means the ads will be 32 pixels dp
which converts to:
32* (480/160) = 96 pixels in landscape
its too bad google doesn't give enough examples so we can really check ourselves.
Your info page is:
https://developers.google.com/admob/android/banner
There is answer:
https://stackoverflow.com/a/14204959/1900546
int heightPixels = AdSize.SMART_BANNER.getHeightInPixels(this);
The following function may come in handy to those of you using Admob Smart Banners:
public static float adHeight(){
float f = Screen.dpi / 160f;
float dp = Screen.height / f;
return (dp>720f)? 90f * f
:(dp>400f)? 50f * f
:32f * f;
}
To use it:
r.offsetMin = new Vector2(r.offsetMin.x, adHeight());
where r is the RectTransform of the fullscreen Canvas / Panel.
I am attaching a 'loadBannerAd' script to every panel which requires it.
The link you gave says that the Smart banner will have a height of
32 dp for phones in landscape
50 dp for phones in portrait
90 dp for tablets in either orientation
Let's take the two examples you gave.
The Nexus 4 has a DPI of ~320 dp. Given that it's a phone, it'll have an ad with a height of 50 dp.
Using the formula, it works out to 50 * 320 / 160 = 100 pixels (close to your actual banner's height)
The Nexus 7s I looked up have either a 216 dp (2012) or 323 dp (2013), so I don't quite know which model has 166 dp.
But let's assume that it's 216 dp, then being a tablet, ad height in dp is 90. Therefore, pixels = 90 * 216 / 160 = 121.5, once again close to your banner's actual height.
I realize that Google has also mentioned the following
For devices with heights between 400 & 720, an ad with a height of 50 is used
For devices with heights above 720, an ad with a height of 90 is used.
However, I believe that the 400 & 720 MIGHT also be expressed in dp? i.e. 400 pixels in an mdpi device. Your Nexus 4 being an xhdpi device (320 dp), with a height of 1280 pixels then would be the same as an mdpi device of height 640 pixels, falling within the range for an ad height of 50 dp.
Bottomline, your calculations seem valid. Stick to the first set of rules, and you should see consistent results.
bannerView.SetPosition(AdPosition.Top);
or something similar to this is how you change a position of an active banner
I have one problem with UI widget sizing, see 2 devices below as an example,
1.) Samsung Galaxy Tab 2 7"
- Pixels : 1024x600 (mdpi)
- DPI : 160
- Density : 1.0
2.) Samsung Nexus 10 2013
- Pixels : 2560x1600 (xhdpi)
- DPI : 320
- Density : 2.0
If I place a widget with 50dp, by using px = dp (DPI / 160), it would be 50px for Tab 7" and 100px for Nexus 10. But in term of percentage, 50px is equal to 4.88% of screen width on Tab 7" while 100px is 3.9% of screen width on Nexus 10.
But, I need this widget to appear with same width percentage. So, I came up with 2 options.
A. Calculate at run time by getting the physical pixels and apply percentage, then resize the widget.
B. Calculate size and place in < dimen > in different xml file (sw600dp and sw700dp for my case).
As of now, I'm using option A to calculate size and set at runtime. It works well but I'm afraid that the calculation could affect the performance. If I choose option B, I will need to calculate size for every widget in every screen (50dp for Tab 7" and 62.5dp for Nexus 10 will result as 4.8% on both). But, if I want to change this value later or some manufacturer introduce new device with difference DPI or pixels (imagine, 7" tablet with hdpi resolution, 1.5 density, 240 DPI), I will have to redo all the calculation and update or provide new xml again.
So, my question is, is there an option C which will not slow down the performance and not taking a lot of manual calculation into account in future?
P.S. Sorry, I forgot to mentioned that I also using weight approach with my static widgets already, but my question is about dynamic-generate widget. For example,
a gridlayout that showing 5 columns on Landscape Tablet
a scrollview to show 4 rows per page on Phone
an ImageView with 5% padding
an ImageView with an aspect ratio on every device.
dp are almost equal on all devices in size, not in screen %
If you need same screen % then just get display size & calculate desired % of it. Then dynamically apply to your widget
This question already has answers here:
How to get the screen size of the device?
(4 answers)
Closed 9 years ago.
How can I detect the screen size of a android phone in inches?getSize method returns size from pixels ,but when adapting to different screen sizes it not work.There are screen with same pixel size but smaller in inches,in that case some views not get required space in screen.If can't get size in inches can do same thing using pixel size?
You will be getting pixels right convert to inches by,,,
To get the size of a lets say how much 1pixel = x inches. Ask the person to get a ruler and put it on the screen and measure the width of a line e.g. 320 pixel's line. Then you'll know 320pixels = x inches, given x 320/x = 1 inch.
Or
For your map just let x pixels = y inches and the map would be scaled vertically and horizontally by different factors the person would have a good idea in size provided you show a horizontal and vertical scale.
Edit
Hey I got a better way to do this, but it doesn't work when the screen does not fill the entire monitor (commonly on CRT monitors). Just ask for the size of the monitor the person is using and your set with everything you need. The ratios of 1024x768, 800x600, 640x480 are all 4/3, so is the height and width of the physical monitor. 15" monitors go up by 9" and left by 12". so the height in pixels is split evenly in 9" and width is split evenly in 12". Therefore:
x_screen_resolution = 12"
y_screen_resolution = 9"
Now you have your conversion factor from pixels to inches for a 15" monitor. The ratio 4/3 is probably a standard so if you get in inches Z of the size of the monitor then
x*x + y*y = Z*Z ... eq1
x/y = 4/3 .... eq2
x = 4y/3 ...
16yy/9 + yy = ZZ
25yy/16 = 9ZZ/16
yy = 9ZZ/25
-------------
y = 3Z/5
We now know y solve for screen width x
x = sqrt(ZZ-yy)
and thus
x_screen_resolution = x inches
y_screen_resolution = y inches
hope it helps
I'm trying to define a line in Android which measure must be 10cm wide.
I tried to put the width in mm and inches, but the results weren't satisfactory.
Also, I tried to follow this link: draw square 3x3 cm in Android
Desperately, i tried to measure 10cm in dip on the screen, but not is the same length in all screens
Is there any way to get it?
Thanks
I think:
height of screen (cm) / height resolution(pixel) * 3 = 3 cm height in pixel for that screen and resolution.
width of the screen (cm) / width resoluzion(pixel) * 3 = 3 cm width in pixel for that screen and resolution.
Not sure about this.
REFER LINK TO GET dpi
nbpixel(1 inch) = densityDpi
so convert 1 cm to inch who give approximativly 0.4 inch
nbpixel(1cm) = 0.4 * densityDpi
So for make a ligne of one cm you must draw 0.4*DPI pixel
To draw a line of 1 cm, you must use multiple dpi (pixel density) to find the number of physical pixels.
dpi/2.54
Mobile device displays also have something which is called devicePixelRatio. You might want to check that too. When building RealRuler (online ruler) I used to multiple mobile screen width/height with that ratio to get actual size. Not sure if it impacts actual size in cm in Android.
All this is very tricky.
An inch or a mm are unit of linear measurement on a surface, which could be a screen or a piece of paper.I'm strange if the result is not satisfactory for you.See this answer for more details.
One would say that if the Galaxy Tab screen resolution (in portrait mode) is 600px and the screen width is 3.55inch, the screen density would be 600/3.55 = 169 dpi. Knowing that and keeping in mind the way the device independent pixels (dp) is computed (http://developer.android.com/guide/practices/screens_support.html):
px = dp * (dpi / 160);
600 = dp * (169 / 160);
dip = 568
So drawing a horizontal line of 568dp (device independent pixels) width starting at position 0 must exactly match the width of the screen. But if you try this on device you will find that the screen width is 400dp. I will use the same formula again but for getting dpi:
600 = 400 * (dpi / 160);
dpi = 240
So having the 240dpi, 3.55inch screen width and 600pixels, does it mean that one physical pixel is composed of more ‘dots’ otherwise the parameters corresponds to the width of 852pixel (3.55*240).
I thought that dpi means dots per inch, which is pixels per inch. But this seems to not be true...
Added later:
This (http://developer.android.com/guide/topics/resources/more-resources.html#Dimension) says:
160dp is always one inch regardless of the screen density
Which is not true. Just check the measurement source from this:
Difference between android dimension: pt and dp
Added even later:
The reason I am asking is that violating the rule that 160dp = 1inch leads to the fact that when specifying the control width to e.g. 320dp it will cover on Galaxy Tab much bigger portion that that really necessary and much bigger then what you would expect from 600x1024px screen...
Thanks for clarification
BR
STeN
Galaxy Tab (7") doesn't report its real density. To understand this issue, read the following article:
http://realmike.org/blog/2010/12/21/multiple-screen-sizes-with-processing-for-android/
Apparently, that’s also what Samsung found when they made the Galaxy
Tab. The Galaxy Tab has a 7″, 1024×600 screen with 170 dpi. Yet, the
Tab does not report its density as “mdpi” but as “hdpi”, so the layout
looks exactly as in the second screenshot. If they used “mdpi”, the
icons would be .28″ wide, with “hdpi”, they are .42″ wide—not a big
deal, and I must admit, the layout does look prettier this way.
The article contains some images that will make you understand the problem.