Indhu
Indhu

Reputation: 9956

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?

Upvotes: 965

Views: 918384

Answers (30)

LarsH
LarsH

Reputation: 28004

While applyDimension() will get you from dp to px, as of API level 34, you can use deriveDimension() to go the other way:

float px = 24.0f;
float dp = deriveDimension(COMPLEX_UNIT_PX, px, displayMetrics);

Upvotes: 0

prasobh
prasobh

Reputation: 12241

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
 )

Kotlin extension:

fun Context.toPx(dp: Int): Float = TypedValue.applyDimension(
  TypedValue.COMPLEX_UNIT_DIP,
  dp.toFloat(),
  resources.displayMetrics)

Upvotes: 1168

beigirad
beigirad

Reputation: 5744

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()

val Float.toPx get() = this * Resources.getSystem().displayMetrics.density
    
val Float.toDp get() = this / Resources.getSystem().displayMetrics.density
    

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

PS: According to @EpicPandaForce's comment:

You should not be using Resources.getSystem() for this, because it does not handle foldables and Chrome OS devices.

Upvotes: 71

younes
younes

Reputation: 832

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;
}

Upvotes: 10

Rolf Carlson
Rolf Carlson

Reputation: 893

The developer docs provide an answer on how to convert dp units to pixel units:

In some cases, you will need to express dimensions in dp and then convert them to pixels. The conversion of dp units to screen pixels is simple:

px = dp * (dpi / 160)

Two code examples are provided, a Java example and a Kotlin example. Here is the Java example:

// The gesture threshold expressed in dp
private static final float GESTURE_THRESHOLD_DP = 16.0f;

// Get the screen's density scale
final float scale = getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale
mGestureThreshold = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);

// Use mGestureThreshold as a distance in pixels...

The Kotlin example:

// The gesture threshold expressed in dp
private const val GESTURE_THRESHOLD_DP = 16.0f
...
private var mGestureThreshold: Int = 0
...
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // Get the screen's density scale
    val scale: Float = resources.displayMetrics.density
    // Convert the dps to pixels, based on density scale
    mGestureThreshold = (GESTURE_THRESHOLD_DP * scale + 0.5f).toInt()

    // Use mGestureThreshold as a distance in pixels...
}

The Java method that I created from the Java example works well:

/**
 * Convert dp units to pixel units
 * https://developer.android.com/training/multiscreen/screendensities#dips-pels
 *
 * @param dip input size in density independent pixels
 *            https://developer.android.com/training/multiscreen/screendensities#TaskUseDP
 *
 * @return pixels
 */
private int dpToPixels(final float dip) {
    // Get the screen's density scale
    final float scale = this.getResources().getDisplayMetrics().density;
    // Convert the dps to pixels, based on density scale
    final int pix = Math.round(dip * scale + 0.5f);
    
    if (BuildConfig.DEBUG) {
        Log.i(DrawingView.TAG, MessageFormat.format(
                "Converted: {0} dip to {1} pixels",
                dip, pix));
    }
    
    return pix;
}

Several of the other answers to this question provide code that is similar to this answer, but there was not enough supporting documentation in the other answers for me to know if one of the other answers was correct. The accepted answer is also different than this answer. I thought the developer documentation made the Java solution clear.

There is also a solution in Compose. Density in Compose provides a one line solution for the conversions between device-independent pixels (dp) and pixels.

val sizeInPx = with(LocalDensity.current) { 16.dp.toPx() }

Upvotes: 0

Manthan Patel
Manthan Patel

Reputation: 1852

((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);
            }
        });
    }
});

Upvotes: -3

Prince Gupta
Prince Gupta

Reputation: 173

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().

Upvotes: 6

Alexander
Alexander

Reputation: 646

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

Upvotes: 4

JarsOfJam-Scheduler
JarsOfJam-Scheduler

Reputation: 3179

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)

Upvotes: 4

Maher Abuthraa
Maher Abuthraa

Reputation: 17846

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

Upvotes: 144

Khemraj Sharma
Khemraj Sharma

Reputation: 59004

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);
}

Upvotes: 25

Muhammad Nabeel Arif
Muhammad Nabeel Arif

Reputation: 19310

/**
 * 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);
}

Upvotes: 952

mr5
mr5

Reputation: 3590

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

Upvotes: 1

Venki WAR
Venki WAR

Reputation: 2027

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);
}

Upvotes: 19

Hitesh Sahu
Hitesh Sahu

Reputation: 45160

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);
    }

Upvotes: 4

Son Nguyen
Son Nguyen

Reputation: 79

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);
    }

Upvotes: -1

Alex
Alex

Reputation: 18542

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);

Upvotes: 110

Gunhan
Gunhan

Reputation: 7045

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

Upvotes: 48

Saeed Masoumi
Saeed Masoumi

Reputation: 8916

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}")

Upvotes: 6

asadnwfp
asadnwfp

Reputation: 742

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);

Upvotes: 48

HaMMeReD
HaMMeReD

Reputation: 2462

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.

Upvotes: 5

Zsolt Safrany
Zsolt Safrany

Reputation: 13620

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.

Upvotes: 226

Pavel Ryzhov
Pavel Ryzhov

Reputation: 5162

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;
    }
}

Upvotes: 8

Michael Zhang
Michael Zhang

Reputation: 141

This workds for me (C#):

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

Upvotes: 2

Kai Wang
Kai Wang

Reputation: 3361

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

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

Density

Upvotes: 6

Temi Mide Adey
Temi Mide Adey

Reputation: 69

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.

Upvotes: 6

Sibin
Sibin

Reputation: 561

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

Upvotes: 7

Mike Keskinov
Mike Keskinov

Reputation: 11908

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;
}

Upvotes: 315

Lorenzo Barbagli
Lorenzo Barbagli

Reputation: 1281

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

Upvotes: 12

neeraj t
neeraj t

Reputation: 4764

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);
}

Upvotes: 42

Related Questions