Home » Android » android – Display metrics minus status bar?

android – Display metrics minus status bar?

Posted by: admin April 23, 2020 Leave a comment

Questions:

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

How to&Answers:

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!

Answer:

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