0

I need to know if the Navigation Bar is horizontal (on the bottom of the screen) or vertical (on the right of the screen).

Right now I'm using this code to get the height, but it returns 48dp even on a phone in landscape (that has a vertical navigation bar):

public  int getNavigationBarHeight() {
    int resourceId = getResources().getIdentifier("navigation_bar_height_landscape", "dimen", "android");
    if (resourceId > 0) {
        return getResources().getDimensionPixelSize(resourceId);
    }
    return 0;
}

Is there an API or a strategy to determine the direction?

David Corsalini
  • 7,958
  • 8
  • 41
  • 66

2 Answers2

1

Usually, you do not need to know whether the Nav bar is vertical or horizontal, because it is automatically deducted from the measurements that you receive when you invoke this code:

Rect visibleFrame = new Rect();
mainActivity.getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleFrame);
int heightOfDisplayInPixels = visibleFrame.height();
int widthOfDisplayInPixels = visibleFrame.width();

This code returns to your app the height and width of the area actually available to the app for its use. It deducts the Nav bar and the status bar from the relevant dimensions.

The only problem with the above code is that if the user happens to have the soft keyboard open, the height of the keyboard will also be deducted from the values returned. And even if you have code that closes the keyboard prior to running the above code, it can take a fraction of a second for the closing of the keyboard to be reflected in the above values. I have found that a delay (e.g., via postDelayed()) of 500 msecs is much more than enough for every test device that I personally use.

Of course, coding such a delay is a kluge with a built-in race condition. Nonetheless, the above code otherwise seems to work correctly, other than this one significant issue, and I have not found a better way to ensure that you have accurate values that account for the Nav bar correctly across all (tested) devices.

Specifically, the values returned by DisplayMetrics, while they do not have the above issue, are not consistent across all devices; for example, the Nav bar is deducted on the Nexus 7, but not on the Kindle Fire HD 7 (which, BTW, is one of the devices that has a vertical Nav bar when in landscape orientation).

There are some marginal cases where you might want to know the actual location of the Nav bar, such as when you want to avoid placing a certain commonly-used control near the Nav bar, so that the user does not accidentally hit Back or Home when trying to use it. But generally speaking, this can be avoided (e.g., by placing that control a good distance from the edges of your main view).

Carl
  • 15,445
  • 5
  • 55
  • 53
0

Why don't you check the screen orientation instead of Nav bar direction. In fact, nav bar become vertical only in landscape so use :

getResources().getConfiguration().orientation

To get the current orientation, but sometimes this method isn't useful, you can try :

public int getScreenOrientation()
{
    Display getOrient = getWindowManager().getDefaultDisplay();
    int orientation = Configuration.ORIENTATION_UNDEFINED;
    if(getOrient.getWidth()==getOrient.getHeight()){
        orientation = Configuration.ORIENTATION_SQUARE;
    } else{ 
        if(getOrient.getWidth() < getOrient.getHeight()){
            orientation = Configuration.ORIENTATION_PORTRAIT;
        }else { 
             orientation = Configuration.ORIENTATION_LANDSCAPE;
        }
    }
    return orientation;
}

Hope this help

Adrien Cerdan
  • 1,005
  • 1
  • 11
  • 21
  • 1
    Navigation Bar, when in landscape, is horizontal in some tablets and vertical in phones. I'm not sure about 7" tablets. – David Corsalini Mar 18 '14 at 10:36
  • Damn you're right ! But i just tried on 7" and nav is vertical in landscape... What is your final goal ? – Adrien Cerdan Mar 18 '14 at 10:39
  • I have a fullscreen photoview with a semitransparent linearlayout at the bottom, containing info about the photo. The content goes under the navigation bar, and so does the linearlayout. I want to set the paddingBottom to ensure this doesn't happens. When using android:fitsSystemWindows="true" the linearlayout behaves strangely, adding space on top (covering more space than needed by the views inside it). – David Corsalini Mar 18 '14 at 10:51
  • I understand but i stuck on your issue, easy way should be to hide the navbar in this activity ! – Adrien Cerdan Mar 18 '14 at 11:05
  • You mean completely? We should rip off such an important element. In fact it's impossible to do it, on every interaction with the window the navigation bar pops up again. – David Corsalini Mar 18 '14 at 11:26
  • You're right, but here is some idea : https://developer.android.com/training/system-ui/navigation.html Good luck :/ – Adrien Cerdan Mar 18 '14 at 11:35
  • This has been addressed here: http://stackoverflow.com/questions/21057035/detect-android-navigation-bar-orientation FYI, my Kindle Fire HD 7 has the Nav bar on the right in landscape. My Nexus 7 has the Nav bar at the bottom, as does my Nexus 10. The Nexus 5 is reported by others to have the Nav bar on the right, as well. So it varies from tablet to table, and you need some code to detect which dimension is affected (such as is provided on the linked page). – Carl Aug 07 '14 at 11:14