I searched this question, and almost all of the answers are like this:
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels;
But the official document says widthPixels is The absolute width of the display in pixels. I run the code above on my Nexus 5, and the width equals 1080. Obviously it is an Pixel value. Is there anything I missed? How can I get a dip value of the screen?
you should convert the result to dips, like:
private int pixelsToDips(int pixels)
{
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (pixels / scale + 0.5f);
}
Related
I am having a hard time to make this right.
Basically I am creating an ImageView and applying a LayoutParameter to it.
LayoutParams lp = new LayoutParams(width, height);
lp.gravity = Gravity.CENTER;
I know that width and height parameters receive pixel numbers, so I am passing them in DP and converting it to absolute pixels using:
public int convertToPixels(float dpSize){
final float density = getResources().getDisplayMetrics().density;
return ((int) (dpSize * density + 0.5f));
}
As far I know, this should make a drawable fill exactly the same area in different screens, right? Unfortunately, that is not happening at all.
Is there something wrong with these methods I am using?
These two emulators below have the same image and the same amount of DP.
Left emulator is 1.0 density and right one is 2.0. Why still does it look
so different ? Don't undertand..
Use :
public class Convert{
public static float convertDpToPixel(float dp){
DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
float px = dp * (metrics.densityDpi / 160f);
return Math.round(px);
}
}
Just use it in a static way:
float requiredPixel = Convert.convertDpToPixel(16.0);
For more info: https://developer.android.com/guide/practices/screens_support.html
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 setting an image programatically so it looks like circle but it looks like oval shape in some devices.
my code is-
int circleLeft = (int) (width * 3.3) / 100;
circleLayoutParams.setMargins(circleLeft, (int) (height * 0.29),
circleLeft, (int) (height * 0.18));
circleMenu.setLayoutParams(circleLayoutParams);
xml-
<com.example.converter.view.CircleLayout
android:id="#+id/main_circle_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_gravity="center_horizontal"
android:background="#drawable/glow_circle"/>
i have put images in drawable folder.what is wrong with this code.is it image size problem?
I encountered same problem in my app. It is because variation of PPI and Screen size of different devices. I solved it by getting screen size. It can be done by following code:-
//method to get screen size
public ArrayList<Integer> GetDeviceScreenSize()
{
ArrayList<Integer> size= new ArrayList<Integer>();
if((android.os.Build.VERSION.SDK_INT >= 13)){
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int w = metrics.widthPixels;
int h = metrics.heightPixels;
size.add(0,w);
size.add(1,h);
}else{
Display display = ((WindowManager)ctx.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
size.add(0, width);
size.add(1,height);
}
return size;
}
After you get device screen size through this method, you can set height and width of some part of height and width you got from this method. It should be like:-
ArrayList<Integer> size= GetDeviceScreenSize();
float width = (( (float)size.get(0))/320)*135;
int circleLeft = (int) (width * 3.3) / 100;
Remember, you'll have to try dividing and multiplying the device width and height with different units to get the exact size that you want, but once you get it, It will work on all devices, no matter what is there screen size.
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);