Search code examples
xamarinxamarin.androidpixeldensity-independent-pixel

How to convert dp to px in xamarin.android?


I want to convert dp to px in my C# code in xamarin.android, but all I could find were java codes in android studio that have some problems in xamarin. I tried to use equivalent like using Resources instead of getResources() and I could solve some little problems, but there are some problems yet that I couldn't find any equivalent for them. here are original codes, my codes, and my codes problems in xamarin:

First code

(found from Programatically set height on LayoutParams as density-independent pixels)

java code

int height = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, < HEIGHT >, getResources().getDisplayMetrics());

C# code

int height = (int)TypedValue.ApplyDimension(TypedValue.COMPLEX_UNIT_DIP, < HEIGHT >, Resources.DisplayMetrics);

problems:

  • 'TypedValue' does not contain a definition for 'COMPLEX_UNIT_DIP'

  • Invalid expression term < (The same error for >)

  • The name 'HEIGHT' does not exist in the current context

Second code

(found from Formula px to dp, dp to px android)

java code

DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));

C# code

DisplayMetrics displayMetrics = Application.Context.Resources.DisplayMetrics;
int pixel = Math.Round(dp * (displayMetrics.Xdpi / DisplayMetrics.DensityDefault));

problem

  • Operator '/' cannot be applied to operands of type 'float' and 'DisplayMetricsDensity'

Now I have actually two questions. Which code is more proper? What's equivalent code for them in xamarin.android?

Thanks in advance.


Solution

  • Solution to "First code":

    Xamarin tends to move constants into their own enums. COMPLEX_UNIT_DIP can be found on ComplexUnitType enum. Also you cannot have < HEIGHT > in your code you actually need to pass in dips to get the equivalent pixel value. in the example below I am getting pixels in 100 dips.

    var dp = 100;
    int pixel = (int)TypedValue.ApplyDimension(ComplexUnitType.Dip, dp, Context.Resources.DisplayMetrics);
    

    Solution to "Second code":

    You need to explicitly cast 'DisplayMetrics.DensityDefault' to a float and the entire round to an int:

    int pixel = (int)System.Math.Round(dp * (displayMetrics.Xdpi / (float)DisplayMetrics.DensityDefault));
    

    I prefer the first approach as the second code is specifically for calculating along the "x dimension": Per Android docs and Xamarin.Android docs, the Xdpi property is

    "The exact physical pixels per inch of the screen in the X dimension."