Categories
android dimensions layout pixel screen

How to get screen dimensions as pixels in Android

1937

I created some custom elements, and I want to programmatically place them to the upper right corner (n pixels from the top edge and m 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 and screenHeight in the main Activity?

5

  • Use dp instead of px. because it will distort your layout with other devices..

    Apr 24, 2014 at 6:13

  • Don’t forget to multiply by getResources().getDisplayMetrics().density to account for display scaling

    – jmaculate

    Jun 16, 2014 at 12:53

  • This 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 explains getDisplayMetrics 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.

    – Armfoot

    Sep 2, 2014 at 10:32


  • DisplayMetrics displaymetrics = new DisplayMetrics(); getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); int height = displaymetrics.heightPixels; int width = displaymetrics.widthPixels;

    – Azahar

    May 1, 2015 at 5:30

  • another way to get the DisplayMetrics : Resources.getSystem().getDisplayMetrics(). You won’t need a Context to get them.

    – Täg

    Feb 8, 2019 at 8:56

3556

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

24

  • 15

    getWidth() or getSize()? What would I use if I need my app to run on API <13 as well as API >13?

    – Carol

    Apr 1, 2012 at 5:29

  • 54

    try { display.getSize(size); width = size.x; height = size.y; } catch (NoSuchMethodError e) { width = display.getWidth(); height = display.getHeight(); }

    – Arnaud

    May 12, 2012 at 11:41


  • 255

    I don’t see why you want to use try/catch for such a check? Why not simply use if (android.os.Build.VERSION.SDK_INT >= 13) without any thrown exception at all? I think of try/catch in a normal app-flow as bad practice.

    – Patrik

    Nov 28, 2012 at 15:41

  • 4

    @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.

    – Patrik

    Dec 30, 2012 at 10:16


  • 14

    what if you want to get the screen size excluding the navigation bar and/or notification bar

    May 12, 2013 at 23:24

388

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

9

  • 18

    Note that the metrics (width, height) change depending on the rotation of the device.

    – Tony Chan

    Nov 28, 2011 at 2:17

  • 9

    Metrics 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.

    – Guy

    Dec 29, 2011 at 11:12

  • 4

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

    – Hagai L

    Mar 28, 2012 at 11:00

  • 82

    Also exists this way: getContext().getResources().getDisplayMetrics().widthPixels

    – Nik

    Jul 11, 2012 at 5:32

  • 1

    final 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.

    Feb 20, 2014 at 4:45


123

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.

8

  • 1

    or just write view.post

    Sep 19, 2013 at 9:27

  • 1

    view.post is not guaranteed to work though. It is just a workaround.

    – marsbear

    Feb 25, 2014 at 14:31

  • 1

    @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.

    – Tony Chan

    Mar 22, 2014 at 0:20

  • 1

    @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.

    – marsbear

    Mar 28, 2014 at 15:30


  • 1

    @marsbear does it matter which View you get the ViewTreeObserver from? Or do they all share the same one?

    – Tony Chan

    Apr 9, 2014 at 20:58