35

I need to get the dimensions of the display rectangle that the application can use on the device. For that I tried using:

Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();

My problem is that it gives me the height of the whole display and the display has a "status / notification" bar on top that the application can't use.

I need the acual dimension that the application can use.

To help you understand the question better I'll leave an image:

enter image description here

CanSpice
  • 34,814
  • 10
  • 72
  • 86
J-Rou
  • 2,216
  • 8
  • 32
  • 39

2 Answers2

40

The biggest trick to all of this is that you can't usually gain access to a true value of that view's size until layout is complete. Which means onCreate() (and often onResume() also) are too early in the process to do the calculation. The following code will get you a view representing the content view of the Activity, at which point you can examine its height and width:

View content = getWindow().findViewById(Window.ID_ANDROID_CONTENT);
Log.d("DISPLAY", content.getWidth() + " x " + content.getHeight());

This also accounts for any title views you may have set in the Activity. You could also obtain a reference to the root layout you set as the content view when the XML is inflated and do the same thing if that layout is set to fill_parent in both dimensions.

A good method where I often make calls like this is onWindowFocusChanged() which will be called at the point when your Activity is just about visible to the user.

Hope that Helps!

devunwired
  • 62,780
  • 12
  • 127
  • 139
  • If this works, you wouldn't have only solved my problem, but you would have reduced my code a lot. I've had MANY problems with views not returning their size whe fillParent and MatchParent were used. – J-Rou May 04 '11 at 17:01
  • That gives me the whole display metrics (the same values I got before), but it allowed me to get the size of a gallery I had that had MATCH_PARENT, MATCH_PARENT and whose parent was the usable part of the screen, so I was able to get what I wanted. Thank you verry much, I've been trying to get this solved for a long time. – J-Rou May 04 '11 at 17:08
  • 1
    Nice tip to make the call in `onWindowFocusChanged()` . I was desperate to find a method that allows measuring views at startup. – Sébastien Apr 19 '12 at 18:37
  • This does work, but the activity is on the screen by the time onWindowFocusChanged is called so I can't use it for initial setup. Shame! – Ben Clayton Jan 07 '13 at 17:22
  • You could also try using `onAttachedToWindow()`, or simply make the root view of your layout a custom subclass of a layout that allows you to monitor `onMeasure()` or `onSizeChanged()`. – devunwired Jan 07 '13 at 17:36
  • Must do this inside ViewTreeObserver. That is what it is for. – Greg Ennis Aug 02 '14 at 21:28
  • If you open keyboard, it will return height of screen, that belong to application (screenHeight - statusBarHeight - keyboardHeight) – Vitaliy L Jun 30 '15 at 09:54
10

This call is independent of the point of time you call it:

...
Point dimensions = getDisplayDimensions(context);
int width = dimensions.x;
int height = dimensions.y;
...

@NonNull
public static Point getDisplayDimensions( Context context )
{
    WindowManager wm = ( WindowManager ) context.getSystemService( Context.WINDOW_SERVICE );
    Display display = wm.getDefaultDisplay();

    DisplayMetrics metrics = new DisplayMetrics();
    display.getMetrics( metrics );
    int screenWidth = metrics.widthPixels;
    int screenHeight = metrics.heightPixels;

    // find out if status bar has already been subtracted from screenHeight
    display.getRealMetrics( metrics );
    int physicalHeight = metrics.heightPixels;
    int statusBarHeight = getStatusBarHeight( context );
    int navigationBarHeight = getNavigationBarHeight( context );
    int heightDelta = physicalHeight - screenHeight;
    if ( heightDelta == 0 || heightDelta == navigationBarHeight )
    {
        screenHeight -= statusBarHeight;
    }

    return new Point( screenWidth, screenHeight );
}

public static int getStatusBarHeight( Context context )
{
    Resources resources = context.getResources();
    int resourceId = resources.getIdentifier( "status_bar_height", "dimen", "android" );
    return ( resourceId > 0 ) ? resources.getDimensionPixelSize( resourceId ) : 0;
}

public static int getNavigationBarHeight( Context context )
{
    Resources resources = context.getResources();
    int resourceId = resources.getIdentifier( "navigation_bar_height", "dimen", "android" );
    return ( resourceId > 0 ) ? resources.getDimensionPixelSize( resourceId ) : 0;
}

The trick is that it compares the screen display metrics (what you want modulo the status bar) and the "real metrics", which is the physical pixels of the device.

The status bar height then is subtracted ad-hoc if that did not happen yet.

(In my tests the navigation bar, containing back and home buttons, was already subtracted.)

Peter F
  • 3,633
  • 3
  • 33
  • 45