Devices Display Settings (ie Android Screen Zoom & Font) - android

I have been tasked to complete an Andoid app alongside our existing IOS app.
The project skeleton for Android is already there I just need to fill in the gaps to bring it up to speed with the IOS version.
I have been testing via my own phone and have been struggling with fonts being too large on my Galaxy S6.
Now I have just realised that this is due to the actual Zomm and Font display settings on my device (my eyesite isn't the best).
My question is, is it possible to retrieve these zoom settings from my device so that I can adjust font's etc accordingly?
Pretty new to Xamarin but I'm getting there - hopefully you'll have some pointers to help me get further.

As we all know, the conversion formula from dp and px: px = dp * density
It can be seen that if the design width is 360dp, we can only modify the value of density if we want to ensure that the px values calculated by all devices are exactly the width of the screen.
By reading the source code and official document, we can see that the density is a member variable in DisplayMetrics, and the DisplayMetrics instance is available through Resources#getDisplayMetrics, and the Resouces is obtained through the Activity or Application Context.
We can familiarize ourselves with the following variables related to DisplayMetrics neutralization adaptation:
DisplayMetrics#density is the above density
DisplayMetrics#densityDpi is the above dpi
DisplayMetrics#scaledDensity The scaling factor of the font, which is
equal to the density under normal conditions, but will change this
value after adjusting the system font size.
Solution:
The following assumes that the design map width is 360dp and is adapted to the wide dimension.
Then the adapted density = device real width (unit px) / 360, then we only need to modify our calculated density in the system, the code is implemented as follows:
private static void setCustomDensity( Activity activity,Application application)
{
DisplayMetrics appDisplaymetrics = application.Resources.DisplayMetrics;
float targetDensity = appDisplaymetrics.WidthPixels / 360;
int targetDensityDpi = (int)(160 * targetDensity);
appDisplaymetrics.Density = appDisplaymetrics.ScaledDensity = targetDensity;
appDisplaymetrics.DensityDpi = (Android.Util.DisplayMetricsDensity)targetDensityDpi;
DisplayMetrics activityDisplayMetrics = activity.Resources.DisplayMetrics;
activityDisplayMetrics.Density = activityDisplayMetrics.ScaledDensity = targetDensity;
activityDisplayMetrics.DensityDpi = (Android.Util.DisplayMetricsDensity)targetDensityDpi;
}
Also called in the Activity#onCreate method. The code is relatively simple, and does not involve the call of the system non-public api, so theoretically it will not affect the stability of the app.
Note: If you switch fonts in the system settings and then return to the app, the fonts have not changed. So you have to listen to the font switch, call Application#registerComponentCallbacks to register the onConfigurationChanged listener.

Related

How to calculate device pixel ratio

I would like to know how the -webkit-device-pixel-ratio is calculated. I had already read this. Yet I am unable to understand it clearly.
I would also like to know if there is a list of which devices use which pixel ratio. The android website says
The Android Browser and WebView support a CSS media feature that allows you to create styles for specific screen densities—the -webkit-device-pixel-ratio CSS media feature. The value you apply to this feature should be either "0.75", "1", or "1.5", to indicate that the styles are for devices with low density, medium density, or high density screens, respectively.
but I found that we need to use -webkit-device-pixel-ratio=2 to make a web application compatible on 768 x 1280 resolution screen.
According to this article
http://www.html5rocks.com/en/mobile/high-dpi/
The magic number seems to be 150.
Dividing the physical ppi by the ideal ppi of 150, gives the device pixel ratio.
E.g. a device with 445ppi would have a dpr of 3 ->> 445 / 150
The simple calculation seems to hold up okay for many items on this list,
http://en.wikipedia.org/wiki/List_of_displays_by_pixel_density
You can find many of your screen parameters by visiting https://www.mydevice.io/
you can find the pixel ratio using javascript window.devicePixelRatio
Device Pixel Ratio (DPR) is the relationship between physical hardware-based pixels and Device-Independent Pixels which are an abstraction. The value of the device pixel ratio is not something which can reliably be calculated as it's based on how the device manufacturer intends to map one type of pixel system to the other. To reliably obtain this information, you will need to request it from the device.
The problem is that there is no one database with all of (even the most common) devices listed, so looking up the viewport specs for a given device are a case of trying to find the device in any one of several databases.
These are the databases that I've come across and used, that list device viewports along with their pixel ratios:
https://yesviz.com/devices.php (currently the most comprehensive)
http://dpi.lv/
https://www.mydevice.io/#compare-devices
https://viewportsizer.com/devices/
http://screensiz.es
Feel free to add to the list above, as I'm sure there are much more comprehensive databases out there.
Also remember that resolution / DPR = viewport, so for testing the responsiveness of a site you generally only need one of either DPR or viewport, and the viewport itself is generally better.
claculate display metrics and get
DisplayMetrics dm = context.getResources().getDisplayMetrics();
int densityDpi = dm.densityDpi
and use dm.xdpi, or dm.ydpi i.e pixcel desity

How can my flash app fit correctly in all Android devices?

I am making a Flash game for Android devices. I made my game to fit the dimensions of an HTC EVO 4G, but when I play it on a different device such as a Motorola Droid 2 with different dimensions; it does not fill up the whole screen. How do I make it so that my flash game fits the screen correctly of all Android devices?
You need to avoid using absolute numbers. So instead of setting your game to run at 800px in width, you make it run at stage.stageWidth and you use resize functions (add an Event.RESIZE listener to stage) to make sure everything fits within that. The idea is to completely eliminate any hard values. Everything should be relative.
You should also avoid setting the stage size on mobile devices entirely. I cannot remember if that will even work in AIR, honestly. Avoid setting stage size, and avoid setting stage.scaleMode too
So you want to center something? On the 800px screen, you may have set the x value to 450px for a 100px wide object. Now, you need to set it to (stage.stageWidth - object.width ) / 2. Things like that. My guess is you will have to rewrite a significant portion of your game to do this.
It's also worth noting that your assets are likely too small for higher-resolution screens. The EVO 4G was just 217 dpi. Nowadays, there isn't a high-end phone out there lower than 320 dpi (the iPhone) with many in the mid-400's. Android currently supports as high as 680 dpi, I believe.
Long story short, if you are programming for a single screen size, you are doing it completely wrong. Everything you do, no matter what device or platform or os or technology, should be screen-independent at this point.
There may be an easier way to do this but you can listen for the Resize event which will give you the correct stage size for the device you are on. Once it has been fired, you can calculate the your new scale factor based on the new size then apply that scaling to your display objects. The 800 x 480 is just going to be whatever resolution you are targeting to being with, you can make constants for these values. I've tried it and it works but like I said there may be an easier way.
public class MyApp extends Sprite
{
public static var _scaleFactorX:Number = 1.0;
public static var _scaleFactorY:Number = 1.0;
public function MyApp ()
{
super();
// support autoOrients
stage.align = StageAlign.TOP_LEFT;
stage.scaleMode = StageScaleMode.NO_SCALE;
this.stage.addEventListener(flash.events.Event.RESIZE, resize);
}
public function init():void
{
// Set up our scale factor
_scaleFactorX = this.stage.stageWidth / 800;
_scaleFactorY = this.stage.stageHeight / 480;
}
protected function resize(event:Event):void
{
this.stage.removeEventListener(flash.events.Event.RESIZE, resize);
init();
}
}
Set the stage scale mode to "no border":
import flash.display.StageScaleMode;
stage.scaleMode = StageScaleMode.NO_BORDER;
You could try this tutorial
Very simple and well defined. I'm using the same approach for my projects and works fine.

Android set View visibility programmatically based on screen size

I have a view in my android app that I would like to toggle between visible/gone on smaller screens, and visible/invisible in larger sizes. The initial set up (gone for small, invisible for large screens) is done by having two separate XML layout files under layout and layout-sw600dp-land, but then when I need to dynamically swap the visibility setting, how can I determine from within Java code which one to pick based on screen size?
Edit: more specifically, I want to detect in my code the same condition that causes Android to use layouts from layout-sw600dp-land. I was thinking even recording the value somewhere in the values-sw600dp-land directory, but not sure which file to put it into and how to access it.
You can get the size in pixels of the screen using the following.
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
int height = dm.heightPixels;
However, your question was ambiguous as to whether size of screen meant pixels or inches. You may need to take advantage of the dm.densityDpi value, to convert the values from pixels to inches, for a more useful calculation of the "size" of the screen.
ANSER FOR EDITS:
There are two potential solutions. One is referenced in this thread, very simple and you alluded to it above.
How to programatically determine which XML layout my Android apps is using?
The second isn't a solution, but rather an explanation. The layout-sw600dp-land file replaces an old naming convention pre 3.2 that went like this layout-xlarge-land. This essentially manes "xlarge" screen in "landscape" mode. So you can detect this programmatically by finding xlarge screen sizes, in which the width > height. Below is a good reference to compare the old convention vs the new "sw600dp" = smallest width is 600 dp convention.
http://developer.android.com/training/multiscreen/screensizes.html

How to adjust Screen Resolution?

In android there are many different types of screen Resolutions available. How to adjust the screen resolutions using java code?
There is no way to alter the screen resolution programmatically. AFAIK, you'd need to do a hardware level modification to change it.
Instead, you must write your app in a manner that it scales well across displays. Use multiple images for different sizes and densities, use dp units instead of px units. Make layouts for different screen sizes. All of this and more is explained in the online documentation here.
If you are asking about how to make your App adjust to the device resolution, you should read the screen resolution using code below and make your app fill the space as your wish.
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
As there are 1000s of different Android devices, you just can't have a single line of code to do it automatically for you.
If you are speaking about changing the screen resolution like in PCs. LCD screens have native resolutions which cannot be altered. However, in PCs, the driver or the hardware behind the monitor change the resolution by considering consecutive pixels as single pixel. This option is added in high resolution monitors just to keep the compatibility with old video cards. In mobile phones, we do not have a need for doing this, so there is no such options. When LCD monitors replaced CRT, they had a need to work in different resolutions like CRT which can work on more than one native resolutions.
public int AR(int input)
{
final float scale = getResources().getDisplayMetrics().density;
return (int) (input * scale + 0.5f);
}
where, input is the value you want to use.
Example:
ImageView TitleImage = new ImageView(this);
TitleImage.setPadding(AR(10), AR(5), AR(2), AR(3));
NOW THE IMAGE PADDING SUITS ALL KINDS OF RESOLUTIONS.

How to match android application with droid mobile?

i have developed the android application screen resolution is 320x480 Px but i want to run same application without any code modification with Droid Mobile(480x854 px).
i have installed android application with droid mobile but it's displaying only half of the page in droid mobile( i am using the android 2.0 SDK device).
is there any way to resolve this kind of issues?
Regards,
Jeyavel N
Yes: Use density independent pixels (dip) instead of pixels (px) when specifying dimension and position of screen elements. That way, Android will automatically scale these values to different screen resolutions and pixel densities.
When having to specify these programatically, you may find this conversion method useful:
public static int dipToPx(Activity context, int dip) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
return (int) (dip * displayMetrics.density + 0.5f);
}
By just following that, and a little fine tuning, I was able to get our app running on all different screen sizes out there.

Categories

Resources