Suppose I have a value say :-
360dp for a device that is:
Resolution: 1280x800
sw800dp
mdpi
Now I know this dp value works well for the device. How do I calculate the dp value for a device that is:
1024x600
sw600dp
Edit 1:
Maybe I didn't make myself clear. I know what the width must be in dp for a give device typeA with certain resolution R1. How do I calculate the dp value should be for another device typeB with resolution R2?
mdpi
and similarly for a device that is:
2560x1600
sw800dp
xhdpi
I guess what I want to know is how does the math work. What would be the way to calculate the dp value to put in different values files.
i think below class is complete solution for your present as well as futer problems ,
public class DisplayUtil
{
private static int DisplayWidthPixels = 0;
private static int DisplayheightPixels = 0;
private static void getDisplayMetrics(Context context)
{
DisplayMetrics dm = new DisplayMetrics();
((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(dm);
DisplayWidthPixels = dm.widthPixels;
DisplayheightPixels = dm.heightPixels;
}
public static int getDisplayWidthPixels(Context context)
{
if (context == null)
{
return -1;
}
if (DisplayWidthPixels == 0)
{
getDisplayMetrics(context);
}
return DisplayWidthPixels;
}
public static int getDisplayheightPixels(Context context)
{
if (context == null)
{
return -1;
}
if (DisplayheightPixels == 0)
{
getDisplayMetrics(context);
}
return DisplayheightPixels;
}
public static int px2dip(Context context, float pxValue)
{
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
}
public static int dip2px(Context context, float dipValue)
{
if (context == null)
{
return 0;
}
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
public static int px2sp(Context context, float pxValue)
{
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (pxValue / fontScale + 0.5f);
}
public static int sp2px(Context context, float spValue)
{
final float fontScale = context.getResources().getDisplayMetrics().scaledDensity;
return (int) (spValue * fontScale + 0.5f);
}
}
ex. just you have to call DisplayUtil.Method-Name !
A set of six generalized densities:
ldpi (low) -120dpi,
mdpi (medium) -160dpi,
hdpi (high) -240dpi,
xhdpi (extra-high) -320dpi,
xxhdpi (extra-extra-high) -480dpi,
xxxhdpi (extra-extra-extra-high) -640dpi.
If running on mdpi device, 150x150 px image will take up 150*150 dp of screen space.
If running on hdpi device, 150x150 px image will take up 100*100 dp of screen space.
If running on xhdpi device, 150x150 px image will take up 75*75 dp of screen space.
And here we go... We have a online calculator...
https://pixplicity.com/dp-px-converter/
I had a similar problem, so tried this and it worked.
Related
I have to support android devices with screen resolution 1280*800(in dp)(KitKat) and 1280 * 752(dp)(Lollipop). The first one is a 10.1 inch tablet and second one is 9.6 inch tablet.
I am using same layout for all device and using externalized dimension to adjust layout for different screen.
But I am not able to separate the device using "values-sw720dp" and "values-sw800dp". If I use sw800dp both of them use the dimen value from sw800dp dimen folder.
How can I give separate dimension for the two devices?
Get your device's screnn inches programmatically and appy dimension
public static double getDeviceInches(Activity activity) {
DisplayMetrics metrics = getMetrics(activity);
int widthPixels = metrics.widthPixels;
int heightPixels = metrics.heightPixels;
float widthDpi = metrics.xdpi;
float heightDpi = metrics.ydpi;
float widthInches = widthPixels / widthDpi;
float heightInches = heightPixels / heightDpi;
return getDiagonalInches(widthInches, heightInches);
}
private static double getDiagonalInches(float widthInches, float heightInches) {
double diagonalInches = Math.sqrt((widthInches * widthInches) + (heightInches * heightInches));
float roundedValue = (float) Math.round(diagonalInches);
return (double)roundedValue;
}
//From this, we can get the information required to size the display:
private static DisplayMetrics getMetrics(Activity activity) {
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
return metrics;
}
public static int convertDpToPx(Context context, int value) {
// Get the screen's density scale
final float scale = context.getResources().getDisplayMetrics().density;
// Convert the dps to pixels, based on density scale(0.5f is for rounding up value) (arrowWidth is 50dp)
int pxValue= (int) (value * scale + 0.5f);
return pxValue;
}
Put your above code in utility class and call getDeviceInches method from your acitivty or fragment class
I need to code the layout of the android widgets using dip/dp (in java files). At runtime if I code,
int pixel=this.getWindowManager().getDefaultDisplay().getWidth();
this return the screen width in pixels (px). To convert this to dp, I coded:
int dp =pixel/(int)getResources().getDisplayMetrics().density ;
This does not seem to be returning correct answer. I made the emulator of WVGA800 whose screen resolution is 480 by 800. When the run the emulator and let the code print the values of pixel and dp, it came to 320 in both. This emulator is 240 dpi whose scale factor would be 0.75.
As #Tomáš Hubálek mentioned;
Try something like:
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
OR
Try old answer:
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);
float density = getResources().getDisplayMetrics().density;
float dpHeight = outMetrics.heightPixels / density;
float dpWidth = outMetrics.widthPixels / density;
I stumbled upon this question from Google, and later on I found an easy solution valid for API >= 13.
For future references:
Configuration configuration = yourActivity.getResources().getConfiguration();
int screenWidthDp = configuration.screenWidthDp; //The current width of the available screen space, in dp units, corresponding to screen width resource qualifier.
int smallestScreenWidthDp = configuration.smallestScreenWidthDp; //The smallest screen size an application will see in normal operation, corresponding to smallest screen width resource qualifier.
See Configuration class reference
Edit: As noted by Nick Baicoianu, this returns the usable width/height of the screen (which should be the interesting ones in most uses). If you need the actual display dimensions stick to the top answer.
2023 Answer simplified for Kotlin:
val widthDp = resources.displayMetrics.run { widthPixels / density }
val heightDp = resources.displayMetrics.run { heightPixels / density }
As one-liner:
val (height, width) = resources.displayMetrics.run { heightPixels/density to widthPixels/density }
For Jetpack Compose:
val (height, width) = LocalConfiguration.current.run { screenHeightDp.dp to screenWidthDp.dp }
How about using this instead ?
final DisplayMetrics displayMetrics=getResources().getDisplayMetrics();
final float screenWidthInDp=displayMetrics.widthPixels/displayMetrics.density;
final float screenHeightInDp=displayMetrics.heightPixels/displayMetrics.density;
You are missing default density value of 160.
2 px = 3 dip if dpi == 80(ldpi), 320x240 screen
1 px = 1 dip if dpi == 160(mdpi), 480x320 screen
3 px = 2 dip if dpi == 240(hdpi), 840x480 screen
In other words, if you design you layout with width equal to 160dip in portrait mode, it will be half of the screen on all ldpi/mdpi/hdpi devices(except tablets, I think)
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width_px = Resources.getSystem().getDisplayMetrics().widthPixels;
int height_px =Resources.getSystem().getDisplayMetrics().heightPixels;
int pixeldpi = Resources.getSystem().getDisplayMetrics().densityDpi;
int width_dp = (width_px/pixeldpi)*160;
int height_dp = (height_px/pixeldpi)*160;
Answer in kotlin:
context?.let {
val displayMetrics = it.resources.displayMetrics
val dpHeight = displayMetrics.heightPixels / displayMetrics.density
val dpWidth = displayMetrics.widthPixels / displayMetrics.density
}
In the new world of Compose on one line
val (height, width) = LocalConfiguration.current.run { screenHeightDp.dp to screenWidthDp.dp }
Get Screen Width and Height in terms of DP with some good decoration:
Step 1: Create interface
public interface ScreenInterface {
float getWidth();
float getHeight();
}
Step 2: Create implementer class
public class Screen implements ScreenInterface {
private Activity activity;
public Screen(Activity activity) {
this.activity = activity;
}
private DisplayMetrics getScreenDimension(Activity activity) {
DisplayMetrics displayMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics;
}
private float getScreenDensity(Activity activity) {
return activity.getResources().getDisplayMetrics().density;
}
#Override
public float getWidth() {
DisplayMetrics displayMetrics = getScreenDimension(activity);
return displayMetrics.widthPixels / getScreenDensity(activity);
}
#Override
public float getHeight() {
DisplayMetrics displayMetrics = getScreenDimension(activity);
return displayMetrics.heightPixels / getScreenDensity(activity);
}
}
Step 3: Get width and height in activity:
Screen screen = new Screen(this); // Setting Screen
screen.getWidth();
screen.getHeight();
This is a copy/pastable function to be used based on the previous responses.
/**
* #param context
* #return the Screen height in DP
*/
public static float getHeightDp(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
return dpHeight;
}
/**
* #param context
* #return the screnn width in dp
*/
public static float getWidthDp(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
return dpWidth;
}
If you just want to know about your screen width, you can just search for "smallest screen width" in your developer options. You can even edit it.
Your problem is with casting the float to an int, losing precision. You should also multiply with the factor and not divide.
Do this:
int dp = (int)(pixel*getResources().getDisplayMetrics().density);
How to get widget size in pixels?
I am using Note 3 smartphone, I took screenshot and calculated manually, should be 1020px x 316px (+-5px), 4x1widget (resizable).
I tried the code bellow, but I get wrong results:
minW_dp=324dp, maxW_dp=439dp, minH_dp=69dp, maxH_dp=88dp.
minW=782px, maxW=1060px, minH=167px, maxH=213px.
How to get real size of widget in pixels?
public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions)
{
int minW_dp = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH);
int maxW_dp = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_WIDTH);
int minH_dp = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT);
int maxH_dp = newOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MAX_HEIGHT);
int minW = dpToPx(minW_dp, context);
int maxW = dpToPx(maxW_dp, context);
int minH = dpToPx(minH_dp, context);
int maxH = dpToPx(maxH_dp, context);
bitmap = Bitmap.createBitmap(minW, maxH, Config.ARGB_8888);
}
public static int dpToPx(int dp, Context context)
{
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
return px;
}
Your dpToPx calculation is wrong. You need to change it from:
int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
to
int px = Math.round(dp * displayMetrics.density);
If you read the Docs it gets obvious why your calculation couldn't work. (Note: DisplayMetrics.xdpi seems to be messed up on some devices as well, see this post)
Following what displayMetrics.xdpi represents:
The exact physical pixels per inch of the screen in the X dimension.
But you don't wanna get the pixels per inch of your screen. You wanna get the scale-factor, that's where displayMetrics.density comes into play:
The logical density of the display. This is a scaling factor for the
Density Independent Pixel unit, where one DIP is one pixel on an
approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),
providing the baseline of the system's display. Thus on a 160dpi
screen this density value will be 1; on a 120 dpi screen it would be
.75; etc.
Note: The Note 3 is a xxhdpi device and thus has a scale-factor of 3.0 (480dpi).
Edit
An other way to calculate the dp->px:
(int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, maxH_dp, context.getResources().getDisplayMetrics());
I am trying to calculate a variable amount of pixels to density independent pixels and vice-versa.
This formula (px to dp): dp = (int)(px / (displayMetrics.densityDpi / 160)); does not work on small devices because it is divided by zero.
This is my dp to px formula:
px = (int)(dp * (displayMetrics.densityDpi / 160));
Could someone give me some pointers?
Note: The widely used solution above is based on displayMetrics.density. However, the docs explain that this value is a rounded value, used with the screen 'buckets'. Eg. on my Nexus 10 it returns 2, where the real value would be 298dpi (real) / 160dpi (default) = 1.8625.
Depending on your requirements, you might need the exact transformation, which can be achieved like this:
[Edit] This is not meant to be mixed with Android's internal dp unit, as this is of course still based on the screen buckets. Use this where you want a unit that should render the same real size on different devices.
Convert dp to pixel:
public int dpToPx(int dp) {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
Convert pixel to dp:
public int pxToDp(int px) {
DisplayMetrics displayMetrics = getContext().getResources().getDisplayMetrics();
return Math.round(px / (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
Note that there are xdpi and ydpi properties, you might want to distinguish, but I can't imagine a sane display where these values differ greatly.
I solved my problem by using the following formulas. May other people benefit from it.
dp to px:
displayMetrics = context.getResources().getDisplayMetrics();
return (int)((dp * displayMetrics.density) + 0.5);
px to dp:
displayMetrics = context.getResources().getDisplayMetrics();
return (int) ((px/displayMetrics.density)+0.5);
Efficient way ever
DP to Pixel:
private int dpToPx(int dp)
{
return (int) (dp * Resources.getSystem().getDisplayMetrics().density);
}
Pixel to DP:
private int pxToDp(int px)
{
return (int) (px / Resources.getSystem().getDisplayMetrics().density);
}
Hope this will help you.
px to dp:
int valueInpx = ...;
int valueInDp= (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, valueInpx , getResources()
.getDisplayMetrics());
Just call getResources().getDimensionPixelSize(R.dimen.your_dimension) to convert from dp units to pixels
Use This function
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, getResources().getDisplayMetrics());
}
Use these Kotlin extensions:
/**
* Converts Pixel to DP.
*/
val Int.pxToDp: Int
get() = (this / Resources.getSystem().displayMetrics.density).toInt()
/**
* Converts DP to Pixel.
*/
val Int.dpToPx: Int
get() = (this * Resources.getSystem().displayMetrics.density).toInt()
px = dp * (dpi / 160)
dp = px * (160 / dpi)
In most of the cases, conversion functions are called frequently. We can optimize it by adding memoization. So,it does not calculate every-time the function is called.
Let's declare a HashMap which will store the calculated values.
private static Map<Float, Float> pxCache = new HashMap<>();
A function which calculates pixel values :
public static float calculateDpToPixel(float dp, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return px;
}
A memoization function which returns the value from HashMap and maintains the record of previous values.
Memoization can be implemented in different ways in Java. For Java 7 :
public static float convertDpToPixel(float dp, final Context context) {
Float f = pxCache.get(dp);
if (f == null) {
synchronized (pxCache) {
f = calculateDpToPixel(dp, context);
pxCache.put(dp, f);
}
}
return f;
}
Java 8 supports Lambda function :
public static float convertDpToPixel(float dp, final Context context) {
pxCache.computeIfAbsent(dp, y ->calculateDpToPixel(dp,context));
}
Thanks.
You can use [DisplayMatrics][1] and determine the screen density. Something like this:
int pixelsValue = 5; // margin in pixels
float d = context.getResources().getDisplayMetrics().density;
int margin = (int)(pixelsValue * d);
As I remember it's better to use flooring for offsets and rounding for widths.
try this
http://labs.skinkers.com/content/android_dp_px_calculator/
If you're looking for an online calculator for converting DP, SP, inches, millimeters, points or pixels to and from one another at different screen densities, this is the most complete tool I know of.
Below funtions worked well for me across devices.
It is taken from https://gist.github.com/laaptu/7867851
public static float convertPixelsToDp(float px){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return Math.round(dp);
}
public static float convertDpToPixel(float dp){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return Math.round(px);
}
// for getting in terms of Decimal/Float
public static float convertPixelsToDp(float px, Context context) {
Resources resources = context.getResources();
DisplayMetrics metrics = resources.getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return Math.round(dp);
}
public static float convertDpToPixel(float dp, Context context) {
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return Math.round(px);
}
// for getting in terms of Integer
private int convertPxToDp(int px, Context context) {
Resources resources = context.getResources();
return Math.round(px / (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
private int convertDpToPx(int dp, Context context) {
Resources resources = context.getResources();
return Math.round(dp * (resources.getDisplayMetrics().xdpi / DisplayMetrics.DENSITY_DEFAULT));
}
________________________________________________________________________________
public static float convertPixelsToDp(float px){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float dp = px / (metrics.densityDpi / 160f);
return Math.round(dp);
}
public static float convertDpToPixel(float dp){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return Math.round(px);
}
private int convertDpToPx(int dp){
return Math.round(dp*(getResources().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));
}
private int convertPxToDp(int px){
return Math.round(px/(Resources.getSystem().getDisplayMetrics().xdpi/DisplayMetrics.DENSITY_DEFAULT));
}
Elegant kotlin solution :)
val Int.dp get() = this / (Resources.getSystem().displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
val Float.dp get() = this / (Resources.getSystem().displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
val Int.px get() = this * Resources.getSystem().displayMetrics.density
val Float.px get() = this * Resources.getSystem().displayMetrics.density
Usage:
val dpValue = 2.dp
val pxFromDpValue = 2.px
Improtant:
I am not sure if Resources.getSystem() will work correctly with orientation changes.
If want to work in for example fragment or activity just add it it in to base fragment or base activity and use it like this:
abstract class BaseFragment : Fragment() {
val Int.dp get() = this / (resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
val Float.dp get() = this / (resources.displayMetrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT)
val Int.px get() = this * resources.displayMetrics.density
val Float.px get() = this * resources.displayMetrics.density
.......
}
Feel free to use this method I wrote:
int dpToPx(int dp)
{
return (int) (dp * getResources().getDisplayMetrics().density + 0.5f);
}
The answer accepted above is not fully accurate. According to information obtained by inspecting Android source code:
Resources.getDimension() and getDimensionPixelOffset()/getDimensionPixelSize() differ only in that the former returns float while the latter two return the same value rounded to int appropriatelly. For all of them, the return value is in raw pixels.
All three functions are implementedy by calling Resources.getValue() and converting thus obtained TypedValue by calling TypedValue.complexToDimension(), TypedValue.complexToDimensionPixelOffset() and TypedValue.complexToDimensionPixelSize(), respectively.
Therefore, if you want to obtain "raw" value together with the unit specified in XML source, call Resources.getValue() and use methods of the TypedValue class.
with help of other answers I wrote this function.
public static int convertToPixels(Context context, int nDP)
{
final float conversionScale = context.getResources().getDisplayMetrics().density;
return (int) ((nDP * conversionScale) + 0.5f) ;
}
DisplayMetrics displayMetrics = contaxt.getResources()
.getDisplayMetrics();
int densityDpi = (int) (displayMetrics.density * 160f);
int ratio = (densityDpi / DisplayMetrics.DENSITY_DEFAULT);
int px;
if (ratio == 0) {
px = dp;
} else {
px = Math.round(dp * ratio);
}
variation on ct_robs answer above, if you are using integers, that not only avoids divide by 0 it also produces a usable result on small devices:
in integer calculations involving division for greatest precision multiply first before dividing to reduce truncation effects.
px = dp * dpi / 160
dp = px * 160 / dpi
5 * 120 = 600 / 160 = 3
instead of
5 * (120 / 160 = 0) = 0
if you want rounded result do this
px = (10 * dp * dpi / 160 + 5) / 10
dp = (10 * px * 160 / dpi + 5) / 10
10 * 5 * 120 = 6000 / 160 = 37 + 5 = 42 / 10 = 4
Here's a other way to do it using kotlin extensions:
val Int.dpToPx: Int
get() = Math.round(this * Resources.getSystem().displayMetrics.density)
val Int.pxToDp: Int
get() = Math.round(this / Resources.getSystem().displayMetrics.density)
and then it can be used like this from anywhere
12.dpToPx
244.pxToDp
I need to code the layout of the android widgets using dip/dp (in java files). At runtime if I code,
int pixel=this.getWindowManager().getDefaultDisplay().getWidth();
this return the screen width in pixels (px). To convert this to dp, I coded:
int dp =pixel/(int)getResources().getDisplayMetrics().density ;
This does not seem to be returning correct answer. I made the emulator of WVGA800 whose screen resolution is 480 by 800. When the run the emulator and let the code print the values of pixel and dp, it came to 320 in both. This emulator is 240 dpi whose scale factor would be 0.75.
As #Tomáš Hubálek mentioned;
Try something like:
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
OR
Try old answer:
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);
float density = getResources().getDisplayMetrics().density;
float dpHeight = outMetrics.heightPixels / density;
float dpWidth = outMetrics.widthPixels / density;
I stumbled upon this question from Google, and later on I found an easy solution valid for API >= 13.
For future references:
Configuration configuration = yourActivity.getResources().getConfiguration();
int screenWidthDp = configuration.screenWidthDp; //The current width of the available screen space, in dp units, corresponding to screen width resource qualifier.
int smallestScreenWidthDp = configuration.smallestScreenWidthDp; //The smallest screen size an application will see in normal operation, corresponding to smallest screen width resource qualifier.
See Configuration class reference
Edit: As noted by Nick Baicoianu, this returns the usable width/height of the screen (which should be the interesting ones in most uses). If you need the actual display dimensions stick to the top answer.
2023 Answer simplified for Kotlin:
val widthDp = resources.displayMetrics.run { widthPixels / density }
val heightDp = resources.displayMetrics.run { heightPixels / density }
As one-liner:
val (height, width) = resources.displayMetrics.run { heightPixels/density to widthPixels/density }
For Jetpack Compose:
val (height, width) = LocalConfiguration.current.run { screenHeightDp.dp to screenWidthDp.dp }
How about using this instead ?
final DisplayMetrics displayMetrics=getResources().getDisplayMetrics();
final float screenWidthInDp=displayMetrics.widthPixels/displayMetrics.density;
final float screenHeightInDp=displayMetrics.heightPixels/displayMetrics.density;
You are missing default density value of 160.
2 px = 3 dip if dpi == 80(ldpi), 320x240 screen
1 px = 1 dip if dpi == 160(mdpi), 480x320 screen
3 px = 2 dip if dpi == 240(hdpi), 840x480 screen
In other words, if you design you layout with width equal to 160dip in portrait mode, it will be half of the screen on all ldpi/mdpi/hdpi devices(except tablets, I think)
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int width_px = Resources.getSystem().getDisplayMetrics().widthPixels;
int height_px =Resources.getSystem().getDisplayMetrics().heightPixels;
int pixeldpi = Resources.getSystem().getDisplayMetrics().densityDpi;
int width_dp = (width_px/pixeldpi)*160;
int height_dp = (height_px/pixeldpi)*160;
Answer in kotlin:
context?.let {
val displayMetrics = it.resources.displayMetrics
val dpHeight = displayMetrics.heightPixels / displayMetrics.density
val dpWidth = displayMetrics.widthPixels / displayMetrics.density
}
In the new world of Compose on one line
val (height, width) = LocalConfiguration.current.run { screenHeightDp.dp to screenWidthDp.dp }
Get Screen Width and Height in terms of DP with some good decoration:
Step 1: Create interface
public interface ScreenInterface {
float getWidth();
float getHeight();
}
Step 2: Create implementer class
public class Screen implements ScreenInterface {
private Activity activity;
public Screen(Activity activity) {
this.activity = activity;
}
private DisplayMetrics getScreenDimension(Activity activity) {
DisplayMetrics displayMetrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
return displayMetrics;
}
private float getScreenDensity(Activity activity) {
return activity.getResources().getDisplayMetrics().density;
}
#Override
public float getWidth() {
DisplayMetrics displayMetrics = getScreenDimension(activity);
return displayMetrics.widthPixels / getScreenDensity(activity);
}
#Override
public float getHeight() {
DisplayMetrics displayMetrics = getScreenDimension(activity);
return displayMetrics.heightPixels / getScreenDensity(activity);
}
}
Step 3: Get width and height in activity:
Screen screen = new Screen(this); // Setting Screen
screen.getWidth();
screen.getHeight();
This is a copy/pastable function to be used based on the previous responses.
/**
* #param context
* #return the Screen height in DP
*/
public static float getHeightDp(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpHeight = displayMetrics.heightPixels / displayMetrics.density;
return dpHeight;
}
/**
* #param context
* #return the screnn width in dp
*/
public static float getWidthDp(Context context) {
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
float dpWidth = displayMetrics.widthPixels / displayMetrics.density;
return dpWidth;
}
If you just want to know about your screen width, you can just search for "smallest screen width" in your developer options. You can even edit it.
Your problem is with casting the float to an int, losing precision. You should also multiply with the factor and not divide.
Do this:
int dp = (int)(pixel*getResources().getDisplayMetrics().density);