简体   繁体   中英

How to REALLY get the navigation bar height in Android

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!

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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM