How to get screen dimensions as pixels in Android
Solution 1
If you want the display dimensions in pixels you can use getSize
:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
If you're not in an Activity
you can get the default Display
via WINDOW_SERVICE
:
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
If you are in a fragment and want to acomplish this just use Activity.WindowManager (in Xamarin.Android) or getActivity().getWindowManager() (in java).
Before getSize
was introduced (in API level 13), you could use the getWidth
and getHeight
methods that are now deprecated:
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth(); // deprecated
int height = display.getHeight(); // deprecated
For the use case, you're describing, however, a margin/padding in the layout seems more appropriate.
Another way is: DisplayMetrics
A structure describing general information about a display, such as its size, density, and font scaling. To access the DisplayMetrics members, initialize an object like this:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
We can use widthPixels
to get information for:
"The absolute width of the display in pixels."
Example:
Log.d("ApplicationTagName", "Display width in px is " + metrics.widthPixels);
API level 30 update
final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
// Gets all excluding insets
final WindowInsets windowInsets = metrics.getWindowInsets();
Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
| WindowInsets.Type.displayCutout());
int insetsWidth = insets.right + insets.left;
int insetsHeight = insets.top + insets.bottom;
// Legacy size that Display#getSize reports
final Rect bounds = metrics.getBounds();
final Size legacySize = new Size(bounds.width() - insetsWidth,
bounds.height() - insetsHeight);
Solution 2
One way is:
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
It is deprecated, and you should try the following code instead. The first two lines of code gives you the DisplayMetrics
objecs. This objects contains the fields like heightPixels
, widthPixels
.
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int height = metrics.heightPixels;
int width = metrics.widthPixels;
Api level 30 update
final WindowMetrics metrics = windowManager.getCurrentWindowMetrics();
// Gets all excluding insets
final WindowInsets windowInsets = metrics.getWindowInsets();
Insets insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.navigationBars()
| WindowInsets.Type.displayCutout());
int insetsWidth = insets.right + insets.left;
int insetsHeight = insets.top + insets.bottom;
// Legacy size that Display#getSize reports
final Rect bounds = metrics.getBounds();
final Size legacySize = new Size(bounds.width() - insetsWidth,
bounds.height() - insetsHeight);
Solution 3
It may not answer your question, but it could be useful to know (I was looking for it myself when I came to this question) that if you need a View's dimension but your code is being executed when its layout has not been laid out yet (for example in onCreate()
) you can setup a ViewTreeObserver.OnGlobalLayoutListener
with View.getViewTreeObserver().addOnGlobalLayoutListener()
and put the relevant code that needs the view's dimension there. The listener's callback will be called when the layout will have been laid out.
Solution 4
(2012 answer, may be out of date) If you want to support pre Honeycomb, you will need to put in backward compatibility prior to API 13. Something like:
int measuredWidth = 0;
int measuredHeight = 0;
WindowManager w = getWindowManager();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
Point size = new Point();
w.getDefaultDisplay().getSize(size);
measuredWidth = size.x;
measuredHeight = size.y;
} else {
Display d = w.getDefaultDisplay();
measuredWidth = d.getWidth();
measuredHeight = d.getHeight();
}
Of course the deprecated methods will eventually be taken out of the the most recent SDKs, but while we still rely on most of our users having Android 2.1, 2.2 and 2.3, this is what we are left with.
Solution 5
I have tried all possible "solutions" unsuccessfully and I noticed that Elliott Hughes' "Dalvik Explorer" app always shows correct dimension on any Android device/OS version. I ended up looking at his open source project that can be found here: https://code.google.com/p/enh/
Here's all the relevant code:
WindowManager w = activity.getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
d.getMetrics(metrics);
// since SDK_INT = 1;
widthPixels = metrics.widthPixels;
heightPixels = metrics.heightPixels;
try {
// used when 17 > SDK_INT >= 14; includes window decorations (statusbar bar/menu bar)
widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);
heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);
} catch (Exception ignored) {
}
try {
// used when SDK_INT >= 17; includes window decorations (statusbar bar/menu bar)
Point realSize = new Point();
Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
widthPixels = realSize.x;
heightPixels = realSize.y;
} catch (Exception ignored) {
}
EDIT: slightly improved version (avoid firing exceptions on non-supported OS version):
WindowManager w = activity.getWindowManager();
Display d = w.getDefaultDisplay();
DisplayMetrics metrics = new DisplayMetrics();
d.getMetrics(metrics);
// since SDK_INT = 1;
widthPixels = metrics.widthPixels;
heightPixels = metrics.heightPixels;
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 14 && Build.VERSION.SDK_INT < 17)
try {
widthPixels = (Integer) Display.class.getMethod("getRawWidth").invoke(d);
heightPixels = (Integer) Display.class.getMethod("getRawHeight").invoke(d);
} catch (Exception ignored) {
}
// includes window decorations (statusbar bar/menu bar)
if (Build.VERSION.SDK_INT >= 17)
try {
Point realSize = new Point();
Display.class.getMethod("getRealSize", Point.class).invoke(d, realSize);
widthPixels = realSize.x;
heightPixels = realSize.y;
} catch (Exception ignored) {
}
Niko Gamulin
Engineer/Researcher, working in the field of Machine Learning.
Updated on March 15, 2022Comments
-
Niko Gamulin about 2 years
I created some custom elements, and I want to programmatically place them to the upper right corner (
n
pixels from the top edge andm
pixels from the right edge). Therefore I need to get the screen width and screen height and then set position:int px = screenWidth - m; int py = screenHeight - n;
How do I get
screenWidth
andscreenHeight
in the main Activity?-
Zar E Ahmer about 10 yearsUse dp instead of px. because it will distort your layout with other devices..
-
jmaculate almost 10 yearsDon't forget to multiply by getResources().getDisplayMetrics().density to account for display scaling
-
Armfoot over 9 yearsThis proves the most up-voted answer is not always the best (& lots of people repeat answers for rep). Instead of getSize and deprecated getWidth/getHeight combo (ignoring errors), try Balaji.K's
getMetrics
. Nik's comment in his answer even explainsgetDisplayMetrics
to consider the system/status bar size. Also you may use density as jmaculate and LoungeKatt explained to have the EXACT value:DisplayMetrics dm = getResources().getDisplayMetrics(); float fwidth = dm.density * dm.widthPixels;
Tested in Android v2.2 (API 8) and v4.0 with good results and no errors/warnings. -
Azahar about 9 yearsDisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); int height = displaymetrics.heightPixels; int width = displaymetrics.widthPixels;
-
Täg over 5 yearsanother way to get the DisplayMetrics :
Resources.getSystem().getDisplayMetrics()
. You won't need aContext
to get them.
-
-
gcb over 13 yearsThis is actually how the documentation tells you to do it... but it's kinda pointless if you are NOT using a view. you may be using something else, e.g. mglsurfaceview.
-
Dori about 13 yearsthis is better as the parent view may not be the size of the display. But make sure that this is done at a point where the view you are querying the size of has already been layed out, which will not usually be inside onCreate(). You can use a custom callback from onWindowFocusChanged(boolean hasFocus) which will be called after all the views have been measured and so on, ensuring you will not receive incorrect dimensions for the view you are interested it...
-
Abhishek Susarla about 13 yearsNo way u can do it in the XML?
-
MR Mido almost 13 years@ Abhishek Susarla : XML usage is general used in a static way you should expect anything to be done dynamically, hope this helps you figure out ur problem.
-
ajacian81 over 12 yearswell explained MR Mido. A lot of people who are new to Android don't understand the purpose of the XML files.
-
Tony Chan over 12 yearsNote that the metrics (width, height) change depending on the rotation of the device.
-
Guy over 12 yearsMetrics will return the size of the display, but HoneyComb and up, your activity will have less space than what's returned due to the system bar.
-
Josef Pfleger over 12 yearsThanks @jcfrei ! - I refactored the answer appropriately.
-
pzulw over 12 yearsIf you use display.getWidth() be sure to set your minSdkVersion to at least 4 in AndroidManifest.xml or you will get incorrect results on some devices.
-
Someone Somewhere over 12 yearsInteresting discovery: in the emulator (Android 8) I've specified "Abstracted LCD density" as 150, but when I look at DisplayMetrics.densityDpi it shows 160.
-
Hagai L about 12 years@Guy it depends on your implementation. You can hide the status bar: requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
-
Carol about 12 yearsgetWidth() or getSize()? What would I use if I need my app to run on API <13 as well as API >13?
-
Arnaud about 12 yearstry { display.getSize(size); width = size.x; height = size.y; } catch (NoSuchMethodError e) { width = display.getWidth(); height = display.getHeight(); }
-
Nik almost 12 yearsAlso exists this way: getContext().getResources().getDisplayMetrics().widthPixels
-
Norbert almost 12 yearsCool but the is one scary thing about this method in the sourcecode: this comment
-
ArtOfWarfare over 11 years@Arnaud Wouldn't it be a better idea to flip flop the try and catch until getWidth() and getHeight() are actually removed from the SDK? It seems to me your code will end up slowing down devices running API < 13 while giving no speed boost for devices running API >= 13? (BTW Carol, your comment is missing the case API == 13.)
-
Arnaud over 11 yearsGood point! I'd bet the majority of devices running API>=13 would less suffer of this than devices running API<13 in terms of performance. Also this would still work until the getWidth is really removed and not just deprecated. Any Android guy to confirm this?
-
Patrik over 11 yearsI don't see why you want to use
try/catch
for such a check? Why not simply useif (android.os.Build.VERSION.SDK_INT >= 13)
without any thrown exception at all? I think oftry/catch
in a normal app-flow as bad practice. -
A-Live over 11 years@CipherCom at least because it might become deprecated as well.
-
Patrik over 11 years@A-Live then the app would break as well (but not crashing). We developers must pre-check a new os version nevertheless and this maybe just conceal a problem. Also with this argument one could/should surround every few code lines with try/catch, which in my opinion is bad practice as mentioned already.
-
A-Live over 11 years@CipherCom as a developer, you must understand the difference of the general and device dependent code, the latter is always better to use with try/catch at Android world in my opinion. And by try/catch I don't mean spamming exceptions at log but preparing a fallback functionality like using default values.
-
Parth Mehrotra about 11 years@Josef How do the software buttons affect these methods?
-
WildBill about 11 yearswhat is 'ctx' in the above code? Is that a reference to something not defined in the code snippet?
-
tom_mai78101 about 11 years@WildBill
ctx
is aContext
variable. -
android developer about 11 yearswhat if you want to get the screen size excluding the navigation bar and/or notification bar
-
Steve Waring about 11 yearsObviously, you can also pass back the height in the bundle too.
-
Andy Cochrane almost 11 yearsThis is the only post here that takes into account the window decorations (statusbar/menu bar). worked great for me.
-
Erik B almost 11 yearsAwesome, however you should never have expected business logic fire exceptions. Exception firing(even when caught) is horrible for performance. Plus you are doing more work than needed if the SDK_INT is > 13. Instead, you should just add some ifs on the Build.VERSION.SDK_INT.
-
Dragan Marjanović almost 11 years@Erik B, I agree. I added improved version. Still I left the part "since SDK 1" just in case something goes wrong in try/catch (I've seen many bad things in Android especially when you think it's impossible something to go wrong so I like to keep it safe :)). Anyway there shouldn't be too mouch overhead since this calculation should be done only once (e.g. values could be kept in some static attributes).
-
TalkLittle almost 11 yearsNote that this code is licensed under GPL v3 which has implications for using in production apps.
-
Lukas Hanacek over 10 yearsor just write view.post
-
Steven L over 10 yearsIt's not subtracting space for on-screen controls (such as on Tablets or Nexus devices). Also, I get a different value (750 vs 800) on my 10" Tablet, depending on whether the Activity is active when the calculation is done. But for my purposes, this is more than fine. Thank you!
-
Adil Malik over 10 yearsYou need to add
@SuppressLint("NewApi")
just above the function signature in order to be able to compile. -
Abandoned Cart over 10 yearsfinal float scale = getResources().getDisplayMetrics().density; int width = (int) (metrics.widthPixels * scale + 0.5f); - You have to account for device density when doing it that way.
-
marsbear over 10 yearsview.post is not guaranteed to work though. It is just a workaround.
-
Tony Chan about 10 years@marsbear where does it say
View.post()
isn't guaranteed to work? I'm curious because I also rely on this method for getting a View's size after layout and was unaware it unreliable. -
marsbear about 10 years@Turbo I say that :p We used that workaround before and it turned out to be unreliable. That workaround is based on the assumption, that the initially layouting is done within the same UIThread turn as the initialization. Hence you could schedule your code to run before the next UI turn via post() and be fine. It turned out that the layouting might take even longer under certain circumstances and the view was still not layouted when the posted code ran. What I do now is add the ViewTreeObserver in onCreate and remove it after the first onLayout. Init your stuff during that first onLayout.
-
Eric Platon about 10 yearsIf this answer gets you wrong screen sizes, see this related question for an extra necessary step.
-
Tony Chan about 10 years@marsbear does it matter which
View
you get theViewTreeObserver
from? Or do they all share the same one? -
marsbear about 10 years@Turbo They should all share the same but the instance you get from getViewTreeObserver might not be valid forever hence you have to check if it is still alive (isAlive()). What I currently do is: getWindow().getDecorView().addOnLayoutChangeListener(). During the first call of the listener I remove it again and call a method in my BaseActivity: afterFirstLayout(). That's where we do calculations that need an initial complete layout cycle
-
Tony Chan about 10 years@marsbear and this method you use always executes at the right time even with the situation you describe about certain views not finishing their layout when View.post() finally executes?
-
marsbear about 10 years@Turbo so far: yes. But with all the different custom Androids out there it might fail one day :) The most secure way is to do your work in onLayout within your own View class but that is not always feasible if you want to 'just' put a view off the screen in onCreate for animation purposes.
-
milosmns over 9 years@androiddeveloper Navigation, notification and action bars are always the same height, dependent on the system. Check out Android docs to see how many y-pixels
-
android developer over 9 years@milosmns They aren't always being visible. it depends on the device - some tablets have the navigation bar with the notifications inside it (I think on Honeycomb, maybe even later), and also, some devices don't have a navigation bar at all, since they have real buttons
-
Armfoot over 9 years@LoungeKatt why do you add 0.5f? Multiplying by scale gives me the right value, adding that 0.5f gets me (e.g.) 800.5...
-
jww over 9 yearsThis crashes on a emulator running Android 4.0 (API 14).
-
auracool over 9 yearsThis should be the accepted answer as it is Platform independent.
-
Abandoned Cart over 9 years@Armfoot to sway rounding without a lot of excess code.
-
Muzikant over 9 yearsTo handle API Level correctly (Pre/Post API 13) use this code: Point windowSize = new Point(); Display defaultDisplay = getActivity().getWindowManager().getDefaultDisplay(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { defaultDisplay.getSize(windowSize); } else { windowSize.x = defaultDisplay.getWidth(); windowSize.y = defaultDisplay.getHeight(); }
-
Sam about 9 yearsI think it's better to get the height and width in one go rather than in separate calls to the APIs because otherwise they could be out of sync. This could happen if the screen orientation is changing while your code is running.
-
digiphd almost 9 yearsYeah, this was back in 2012.
-
sudocoder almost 9 yearssorry, allow me to clarify what I meant. It is highly unlikely that anyone would support API <14 as of 6/22/2015
-
Michel over 8 yearsJust what i needed!
getResources().getDisplayMetrics().heightPixels + result
gives actual fullscreen height. Dragan Marjanović's answer also works but I prefer this much shorter and simpler solution. -
Michel over 8 yearsGPL and depending on reflection to call methods which might not be present in future Android versions. Mhhh
-
Jan Heinrich Reimer over 8 yearsThis approach is outdated as of Android Marshmallow. Status bar height can change from device or Android version. Better use
OnApplyWindowInsetsListener
. -
santaclos about 8 yearsUse getDefaultDisplay().getRealMetrics(metrics) in order to include screen buttons
-
worked about 8 yearsgetActivity().getResources().getDisplayMetrics().widthPixels; from within a fragment.
-
Paul Woitaschek almost 7 yearsYou should use the
WindowManager
formactivity.getWindwoManager()
. Else when entering multi window, you will receive the size of your app in full width mode. -
android developer over 6 yearsWhy reflection, if the function is actually available for API 17 : developer.android.com/reference/android/view/… ? Anyway, this doesn't take into account the current orientation, so it will switch according to it. Here's a solution that will work the same no matter is the orientation: stackoverflow.com/a/47684256/878126 . However, the question of the thread is about the normal sizes, so it doesn't need the real resolution. Just the part that can be used.
-
forlayo about 5 yearsIf using getRealMetricts() you're going to get the full size with windows decorations and these things; just in case someone is wondering how to do this without reflection.
-
Sourav Bagchi almost 4 yearsIs there any support library for backward compatibility?
-
Krishna Meena almost 4 yearsI think no you will have to use earlier method for API level below 30 and this new method for API level 30 and above
-
Federico Navarrete over 2 yearsThis seems to be deprecated.