13

I own a HTC One A9 which has the ability to hide the navigation bar. In my app, I need to get the height of the navigation bar and set a padding corresponding to it. Here's my problem now: When I hide the navigation bar, the padding is still being set (even Snapchat has this problem). My question is: Is there alternative code to this one that makes it work?

public static int getNavBarHeight(Context context) {
    int result = 0;
    int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0) {
        result = context.getResources().getDimensionPixelSize(resourceId);
    }
    return result;
}

Thanks for your help!

Made by FA
  • 710
  • 2
  • 7
  • 27
  • What are you trying to achieve? Shed some details about that. Probably you don't need to calculate navigation bar height at all. – shaktiman_droid Apr 09 '16 at 07:55
  • @Jabbar_Jigariyo I need to set a padding to a bottom view containing ImageButtons and more when the user has a navigation bar (I'm using the transparent navigation bar) – Made by FA Apr 09 '16 at 07:57
  • If you're using transparent nav bar then why would be a need of hiding it ? For those devices which has nav bar, it would be already transparent and for those devices which has physical button, there would be no nav bar. Right ? – shaktiman_droid Apr 09 '16 at 08:03
  • I assume you're using `android:windowTranslucentNavigation` in your `Theme` – shaktiman_droid Apr 09 '16 at 08:03
  • @Jabbar_Jigariyo The HTC One A9 has a fingerprint sensor that works as a home button. And yes, I am – Made by FA Apr 09 '16 at 08:12
  • Check the solution on [link](http://stackoverflow.com/questions/20264268/how-to-get-height-and-width-of-navigation-bar-programmatically) – Anirudh Loya Apr 09 '16 at 11:17
  • Possible duplicate of [How to get height and width of navigation bar programmatically](http://stackoverflow.com/questions/20264268/how-to-get-height-and-width-of-navigation-bar-programmatically) – Sufian May 03 '17 at 11:40

5 Answers5

11

This is the code I use to get the navigation bar size. Its height will be in Point.y

Credit to this answer

public static Point getNavigationBarSize(Context context) {
    Point appUsableSize = getAppUsableScreenSize(context);
    Point realScreenSize = getRealScreenSize(context);

    // navigation bar on the right
    if (appUsableSize.x < realScreenSize.x) {
        return new Point(realScreenSize.x - appUsableSize.x, appUsableSize.y);
    }

    // navigation bar at the bottom
    if (appUsableSize.y < realScreenSize.y) {
        return new Point(appUsableSize.x, realScreenSize.y - appUsableSize.y);
    }

    // navigation bar is not present
    return new Point();
}

public static Point getAppUsableScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    return size;
}

public static Point getRealScreenSize(Context context) {
    WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    Display display = windowManager.getDefaultDisplay();
    Point size = new Point();

    if (Build.VERSION.SDK_INT >= 17) {
        display.getRealSize(size);
    } else if (Build.VERSION.SDK_INT >= 14) {
        try {
            size.x = (Integer)     Display.class.getMethod("getRawWidth").invoke(display);
            size.y = (Integer) Display.class.getMethod("getRawHeight").invoke(display);
    } catch (IllegalAccessException e) {} catch     (InvocationTargetException e) {} catch (NoSuchMethodException e) {}
    }

    return size;
}

Edit: To answer your question I had to use this function since I wanted to add ResideMenu to my app, but ended getting a weird empty margin at the bottom of my app, because of the navigation bar.

So I edited this function added by ResideMenu like this:

@Override
protected boolean fitSystemWindows(Rect insets) {
    // Applies the content insets to the view's padding, consuming that content (modifying the insets to be 0),
    // and returning true. This behavior is off by default and can be enabled through setFitsSystemWindows(boolean)
    // in API14+ devices.

    int bottomPadding = insets.bottom;

    Point p = getNavigationBarSize(getContext());

    if (Build.VERSION.SDK_INT >= 21 && p.x != 0) {
        Resources resources = getContext().getResources();
        int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
        if (resourceId > 0) {
            bottomPadding += resources.getDimensionPixelSize(resourceId);
        }
    }

    this.setPadding(viewActivity.getPaddingLeft() + insets.left, viewActivity.getPaddingTop() + insets.top,
            viewActivity.getPaddingRight() + insets.right, viewActivity.getPaddingBottom() + bottomPadding);
    insets.left = insets.top = insets.right = insets.bottom = 0;
    return true;
}

Hope that will help you.

Community
  • 1
  • 1
ToinToin
  • 192
  • 2
  • 7
2

Use following code to get Navigation bar. However, you need to consider Multi window mode as well as whether Navigation bar is at the bottom or on left side or right side of the window.

getNavigationBarHeight(){
    Resources resources = context.getResources();
    int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
    if (resourceId > 0) {
        return resources.getDimensionPixelSize(resourceId);
    }
    return 0;
}
Mayank Kumar Chaudhari
  • 16,027
  • 10
  • 55
  • 122
1

Here is the simplest answer. You just need to pass the rootView of the activity. The heights will be 0 if the the bars are not shown.

View rootView;
ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> {
    final int statusBarHeight = insets.getInsets(WindowInsetsCompat.Type.statusBars()).top; // in px
    final int navigationBarHeight = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom; // in px

    // do something with the heights

    return WindowInsetsCompat.CONSUMED;
});
Faisal Khan
  • 548
  • 3
  • 16
  • what the heck is this? what variable equals the height after all this is said and done? – Math Machine Sep 30 '22 at 15:32
  • @MathMachine The code is very clear. If you have problem then point out the specific place. – Faisal Khan Sep 30 '22 at 21:33
  • I never claimed to understand lambda functions, but navigationBarHeight is local. How does this give me the navigation bar height? – Math Machine Oct 01 '22 at 19:51
  • @MathMachine The navigation bar height will be stored in the `int navigationBarHeight` variable within the lambda function whenever the `OnApplyWindowInsetsListener` callback is invoked. The height will be obtained asynchronously via the callback, so you will have to use the obtained height accordingly. – Faisal Khan Oct 02 '22 at 13:52
  • So you can only know the height in the lambda function? – Math Machine Oct 02 '22 at 15:29
  • @MathMachine Yes! This function is reliable and will give the heights properly. It may be useful for many usecases. – Faisal Khan Oct 02 '22 at 21:06
  • My question is what if you need to know outside the lambda function? – Math Machine Oct 02 '22 at 22:06
0
    fun Context.isSoftNavigationBarAvailable(): Boolean {
        val navBarInteractionModeId = resources.getIdentifier(
                  "config_navBarInteractionMode",
                  "integer",
                  "android"
        )
        if (navBarInteractionModeId > 0 && resources.getInteger(navBarInteractionModeId) > 0) {
            // nav gesture is enabled in the settings
            return false
        }
        val appUsableScreenSize = Point()
        val realScreenSize = Point()
        val defaultDisplay = (getSystemService(Context.WINDOW_SERVICE) as WindowManager).defaultDisplay
        defaultDisplay.getSize(appUsableScreenSize)
        defaultDisplay.getRealSize(realScreenSize)
        return appUsableScreenSize.y < realScreenSize.y }
Gilbert Parreno
  • 107
  • 1
  • 4
0

From Android R (SDK 30+), you can use this code to get size of status bar and navigation bar

    WindowInsets insets = activity.getWindowManager().getCurrentWindowMetrics().getWindowInsets();
    int statusBarHeight = insets.getInsets(WindowInsetsCompat.Type.statusBars()).top; //in pixels
    int navigationBarHeight = insets.getInsets(WindowInsetsCompat.Type.navigationBars()).bottom; //in pixels
tuantv.dev
  • 108
  • 7