[android] Converting pixels to dp

I have created my application with the height and width given in pixels for a Pantech device whose resolution is 480x800.

I need to convert height and width for a G1 device.
I thought converting it into dp will solve the problem and provide the same solution for both devices.

Is there any easy way to convert pixels to dp?
Any suggestions?

This question is related to android pixel resolution dpi

The answer is


using kotlin-extension makes it better

fun Int.toPx(context: Context): Int = (this * context.resources.displayMetrics.density).toInt()

fun Int.toDp(context: Context): Int = (this / context.resources.displayMetrics.density).toInt()

UPDATE:

Because of displayMetrics is part of global shared Resources, we can use Resources.getSystem()

fun Int.toPx(): Int = (this * Resources.getSystem().displayMetrics.density).toInt()

fun Int.toDp(): Int = (this / Resources.getSystem().displayMetrics.density).toInt()

to convert Pixels to dp use the TypedValue .

As the documentation mentioned : Container for a dynamically typed data value .

and use the applyDimension method :

public static float applyDimension (int unit, float value, DisplayMetrics metrics) 

which Converts an unpacked complex data value holding a dimension to its final floating point value like the following :

Resources resource = getResources();
float dp = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_PX, 69, resource.getDisplayMetrics());

Hope that Helps .


If you can use the dimensions XML it's very simple!

In your res/values/dimens.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <dimen name="thumbnail_height">120dp</dimen>
    ...
    ...
</resources>

Then in your Java:

getResources().getDimensionPixelSize(R.dimen.thumbnail_height);

A lot of great solutions above. However, the best solution I found is google's design:

https://design.google.com/devices/

Density


This should give you the conversion dp to pixels:

public static int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

This should give you the conversion pixels to dp:

public static int pxToDp(int px)
{
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}

To convert dp to px this code can be helpful :

public static int dpToPx(Context context, int dp) {
       final float scale = context.getResources().getDisplayMetrics().density;
       return (int) (dp * scale + 0.5f);
    }

You can use this .. without Context

public static int pxToDp(int px) {
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}

public static int dpToPx(int dp) {
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

As @Stan mentioned .. using this approach may cause issue if system changes density. So be aware of that!

Personally I am using Context to do that. It's just another approach I wanted to share you with


/**
 * This method converts dp unit to equivalent pixels, depending on device density. 
 * 
 * @param dp A value in dp (density independent pixels) unit. Which we need to convert into pixels
 * @param context Context to get resources and device specific display metrics
 * @return A float value to represent px equivalent to dp depending on device density
 */
public static float convertDpToPixel(float dp, Context context){
    return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}

/**
 * This method converts device specific pixels to density independent pixels.
 * 
 * @param px A value in px (pixels) unit. Which we need to convert into db
 * @param context Context to get resources and device specific display metrics
 * @return A float value to represent dp equivalent to px value
 */
public static float convertPixelsToDp(float px, Context context){
    return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}

For Xamarin.Android

float DpToPixel(float dp)
{
    var resources = Context.Resources;
    var metrics = resources.DisplayMetrics;
    return dp * ((float)metrics.DensityDpi / (int)DisplayMetricsDensity.Default);
}

Making this a non-static is necessary when you're making a custom renderer


In case you developing a performance critical application, please consider the following optimized class:

public final class DimensionUtils {

    private static boolean isInitialised = false;
    private static float pixelsPerOneDp;

    // Suppress default constructor for noninstantiability.
    private DimensionUtils() {
        throw new AssertionError();
    }

    private static void initialise(View view) {
        pixelsPerOneDp = view.getResources().getDisplayMetrics().densityDpi / 160f;
        isInitialised = true;
    }

    public static float pxToDp(View view, float px) {
        if (!isInitialised) {
            initialise(view);
        }

        return px / pixelsPerOneDp;
    }

    public static float dpToPx(View view, float dp) {
        if (!isInitialised) {
            initialise(view);
        }

        return dp * pixelsPerOneDp;
    }
}

More elegant approach using kotlin's extension function

/**
 * Converts dp to pixel
 */
val Int.dpToPx: Int get() = (this * Resources.getSystem().displayMetrics.density).toInt()

/**
 * Converts pixel to dp
 */
val Int.pxToDp: Int get() = (this / Resources.getSystem().displayMetrics.density).toInt()

Usage:

println("16 dp in pixel: ${16.dpToPx}")
println("16 px in dp: ${16.pxToDp}")

The best answer comes from the Android framework itself: just use this equality...

public static int dpToPixels(final DisplayMetrics display_metrics, final float dps) {
    final float scale = display_metrics.density;
    return (int) (dps * scale + 0.5f);
}

(converts dp to px)


Preferably put in a Util.java class

public static float dpFromPx(final Context context, final float px) {
    return px / context.getResources().getDisplayMetrics().density;
}

public static float pxFromDp(final Context context, final float dp) {
    return dp * context.getResources().getDisplayMetrics().density;
}

Probably the best way if you have the dimension inside values/dimen is to get the dimension directly from getDimension() method, it will return you the dimension already converted into pixel value.

context.getResources().getDimension(R.dimen.my_dimension)

Just to better explain this,

getDimension(int resourceId) 

will return the dimension already converted to pixel AS A FLOAT.

getDimensionPixelSize(int resourceId)

will return the same but truncated to int, so AS AN INTEGER.

See Android reference


For DP to Pixel

Create a value in dimens.xml

<dimen name="textSize">20dp</dimen>

Get that value in pixel as:

int sizeInPixel = context.getResources().getDimensionPixelSize(R.dimen.textSize);

kotlin

   fun spToPx(ctx: Context, sp: Float): Float {
    return sp * ctx.resources.displayMetrics.scaledDensity
}

fun pxToDp(context: Context, px: Float): Float {
    return px / context.resources.displayMetrics.density
}

fun dpToPx(context: Context, dp: Float): Float {
    return dp * context.resources.displayMetrics.density
}

java

   public static float spToPx(Context ctx,float sp){
    return sp * ctx.getResources().getDisplayMetrics().scaledDensity;
}

public static float pxToDp(final Context context, final float px) {
    return px / context.getResources().getDisplayMetrics().density;
}

public static float dpToPx(final Context context, final float dp) {
    return dp * context.getResources().getDisplayMetrics().density;
}

((MyviewHolder) holder).videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
    @Override
    public void onPrepared(final MediaPlayer mediaPlayer) {
        mediaPlayer.setLooping(true);
        ((MyviewHolder) holder).spinnerView.setVisibility(View.GONE);
        mediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
           @Override
           public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
               /*
               * add media controller
               */
               MediaController controller = new MediaController(mContext);
               float density = mContext.getResources().getDisplayMetrics().density;
               float px = 55 * density;
               // float dp = somePxValue / density;
               controller.setPadding(0, 0, 0, (int) (px));
               ((MyviewHolder) holder).videoView.setMediaController(controller);
            }
        });
    }
});

You can therefore use the following formulator to calculate the right amount of pixels from a dimension specified in dp

public int convertToPx(int dp) {
    // Get the screen's density scale
    final float scale = getResources().getDisplayMetrics().density;
    // Convert the dps to pixels, based on density scale
    return (int) (dp * scale + 0.5f);
}

like this:

public class ScreenUtils {

    public static float dpToPx(Context context, float dp) {
        if (context == null) {
            return -1;
        }
        return dp * context.getResources().getDisplayMetrics().density;
    }

    public static float pxToDp(Context context, float px) {
        if (context == null) {
            return -1;
        }
        return px / context.getResources().getDisplayMetrics().density;
    }
}

dependent on Context, return float value, static method

from: https://github.com/Trinea/android-common/blob/master/src/cn/trinea/android/common/util/ScreenUtils.java#L15


Java code:

// Converts 14 dip into its equivalent px
float dip = 14f;
Resources r = getResources();
float px = TypedValue.applyDimension(
    TypedValue.COMPLEX_UNIT_DIP,
    dip,
    r.getDisplayMetrics()
);

Kotlin code:

 val dip = 14f
 val r: Resources = resources
 val px = TypedValue.applyDimension(
     TypedValue.COMPLEX_UNIT_DIP,
     dip,
     r.displayMetrics
 )

To convert dp to pixel

public static int dp2px(Resources resource, int dp) {
    return (int) TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_DIP,
        dp,resource.getDisplayMetrics()
    );
}

To convert pixel to dp.

public static float px2dp(Resources resource, float px)  {
    return (float)TypedValue.applyDimension(
        TypedValue.COMPLEX_UNIT_PX,
        px,
        resource.getDisplayMetrics()
    );
}

where resource is context.getResources().


PX and DP are different but similar.

DP is the resolution when you only factor the physical size of the screen. When you use DP it will scale your layout to other similar sized screens with different pixel densities.

Occasionally you actually want pixels though, and when you deal with dimensions in code you are always dealing with real pixels, unless you convert them.

So on a android device, normal sized hdpi screen, 800x480 is 533x320 in DP (I believe). To convert DP into pixels /1.5, to convert back *1.5. This is only for the one screen size and dpi, it would change depending on design. Our artists give me pixels though and I convert to DP with the above 1.5 equation.


Without Context, elegant static methods:

public static int dpToPx(int dp)
{
    return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}

public static int pxToDp(int px)
{
    return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}

This workds for me (C#):

int pixels = (int)((dp) * Resources.System.DisplayMetrics.Density + 0.5f);

private fun toDP(context: Context,value: Int): Int {
    return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
        value.toFloat(),context.resources.displayMetrics).toInt()
}

You should use dp just as you would pixels. That's all they are; display independent pixels. Use the same numbers you would on a medium density screen, and the size will be magically correct on a high density screen.

However, it sounds like what you need is the fill_parent option in your layout design. Use fill_parent when you want your view or control to expand to all the remaining size in the parent container.


float scaleValue = getContext().getResources().getDisplayMetrics().density;
int pixels = (int) (dps * scaleValue + 0.5f);

According to the Android Development Guide:

px = dp * (dpi / 160)

But often you'll want do perform this the other way around when you receive a design that's stated in pixels. So:

dp = px / (dpi / 160)

If you're on a 240dpi device this ratio is 1.5 (like stated before), so this means that a 60px icon equals 40dp in the application.


This is how it works for me:

DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int  h = displaymetrics.heightPixels;
float  d = displaymetrics.density;
int heightInPixels=(int) (h/d);

You can do the same for the width.


There is a default util in android SDK: http://developer.android.com/reference/android/util/TypedValue.html

float resultPix = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,1,getResources().getDisplayMetrics())

For anyone using Kotlin:

val Int.toPx: Int
    get() = (this * Resources.getSystem().displayMetrics.density).toInt()

val Int.toDp: Int
    get() = (this / Resources.getSystem().displayMetrics.density).toInt()

Usage:

64.toPx
32.toDp

Kotlin

fun convertDpToPixel(dp: Float, context: Context): Float {
    return dp * (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}

fun convertPixelsToDp(px: Float, context: Context): Float {
    return px / (context.resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
}

Java

public static float convertDpToPixel(float dp, Context context) {
    return dp * ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}

public static float convertPixelsToDp(float px, Context context) {
    return px / ((float) context.getResources().getDisplayMetrics().densityDpi / DisplayMetrics.DENSITY_DEFAULT);
}

float density = context.getResources().getDisplayMetrics().density;
float px = someDpValue * density;
float dp = somePxValue / density;

density equals

  • .75 on ldpi (120 dpi)
  • 1.0 on mdpi (160 dpi; baseline)
  • 1.5 on hdpi (240 dpi)
  • 2.0 on xhdpi (320 dpi)
  • 3.0 on xxhdpi (480 dpi)
  • 4.0 on xxxhdpi (640 dpi)

Use this online converter to play around with dpi values.

EDIT: It seems there is no 1:1 relationship between dpi bucket and density. It looks like the Nexus 5X being xxhdpi has a density value of 2.625 (instead of 3). See for yourself in the Device Metrics.


If you want Integer values then using Math.round() will round the float to the nearest integer.

public static int pxFromDp(final float dp) {
        return Math.round(dp * Resources.getSystem().getDisplayMetrics().density);
    }

Examples related to android

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How to implement a simple scenario the OO way My eclipse won't open, i download the bundle pack it keeps saying error log getting " (1) no such column: _id10 " error java doesn't run if structure inside of onclick listener Cannot retrieve string(s) from preferences (settings) strange error in my Animation Drawable how to put image in a bundle and pass it to another activity FragmentActivity to Fragment A failure occurred while executing com.android.build.gradle.internal.tasks

Examples related to pixel

c++ and opencv get and set pixel color to Mat Calculating width from percent to pixel then minus by pixel in LESS CSS Count all values in a matrix greater than a value Get pixel's RGB using PIL What's the best way to set a single pixel in an HTML5 canvas? Converting pixels to dp Setting width/height as percentage minus pixels How to get screen dimensions as pixels in Android Convert Pixels to Points How to read the RGB value of a given pixel in Python?

Examples related to resolution

Image resolution for new iPhone 6 and 6+, @3x support added? Converting pixels to dp Hide div if screen is smaller than a certain width How can I get screen resolution in java? Set background image according to screen resolution How do I get monitor resolution in Python? Getting the screen resolution using PHP jQuery Screen Resolution Height Adjustment Recommended website resolution (width and height)?

Examples related to dpi

Load dimension value from res/values/dimension.xml from source code Converting pixels to dp How to change resolution (DPI) of an image? getting the screen density programmatically in android?