12

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.

Community
  • 1
  • 1

4 Answers4

17

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."

Steven Mark Ford
  • 3,372
  • 21
  • 32
  • Yes, I prefer the first one too. the second one doesn't work same on different devices because of what you said and also has a warning: 'DisplayMetrics.DensityDefault' is obsolete: 'This constant will be removed in the future version. Use Android.Util.DisplayMetricsDensity enum directly instead of this field.' – Reyhaneh Sharifzadeh Dec 01 '16 at 14:14
  • @ReyhanehSharifzadeh, I understood the concept, could you please tell me why we need to convert the value to pixel? and the pixel value where we need to set. Thank you – Saravanakumar Natarajan Sep 06 '20 at 11:10
12

These are from the project that I am currently working on..

public static float pxFromDp(Context context, float dp)
{
    return dp * context.Resources.DisplayMetrics.Density;
}

public static float dpFromPx(Context context, float px)
{
    return px / context.Resources.DisplayMetrics.Density;
}
Drunken Daddy
  • 7,326
  • 14
  • 70
  • 104
  • 2
    Pretty easy solution, I am using an adjusted version for Xamarin.Forms (v2.3.4247): `var dp= pixels* (int)Resources.System.DisplayMetrics.Density;` – ethane May 30 '17 at 16:04
  • 1
    I use `DeviceDisplay.MainDisplayInfo.Density` from the Xamarin.Essentials import. – Gertjan Brouwer Apr 16 '21 at 18:23
0

From android source code textview settextsize

var convertToDp = TypedValue.ApplyDimension( ComplexUnitType.Dip, size, context.Resouces.DisplayMetrics);
Minute V
  • 25
  • 3
-1

dp to px:


    DisplayMetrics displayMetrics = Application.Context.Resources.DisplayMetrics;
    double pixel = Math.Round((dp * DisplayMetrics.DensityDefault) + 0.5);

Answer taken from here : https://stackoverflow.com/a/8490361/6949388

Sorry, not enough rep to comment.

Morse
  • 8,258
  • 7
  • 39
  • 64
Mojo Allmighty
  • 793
  • 7
  • 18
  • The error is still shown. 'DisplayMetricsDensity' couldn't convert to float or int, so I couldn't apply any operator to this operand and an integer or float operand. – Reyhaneh Sharifzadeh Nov 27 '16 at 17:08
  • @ReyhanehSH you can hard cast float to int, or double to float, it will work. Especially since for UI you don't really mind if you are 0.0000000001 pixels off. But anyhow, the accepted answer is more up to date than this one. – matfillion Apr 05 '17 at 13:59