I am trying to determine soft navigation bar through the android program. I didn't find straight way to determine. Is there anyway to find the navigation bar availability.
Soft Navigation bar image is here.
I am trying to determine soft navigation bar through the android program. I didn't find straight way to determine. Is there anyway to find the navigation bar availability.
Soft Navigation bar image is here.
Following method worked for me and tested in many devices.
public boolean hasNavBar (Resources resources)
{
int id = resources.getIdentifier("config_showNavigationBar", "bool", "android");
return id > 0 && resources.getBoolean(id);
}
Note: Verified this method in real device
false
in both cases. –
Abide false
on the Android emulators. See this commit message for an explanation. –
Apophysis As i know you can detect it by
boolean hasSoftKey = ViewConfiguration.get(context).hasPermanentMenuKey();
But it required APIs 14+
If above solution doesn't work for you then try below method
public boolean isNavigationBarAvailable(){
boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);
return (!(hasBackKey && hasHomeKey));
}
hasBackKey
equals true on Sony Xperia Z3. Which make the second solution fail. –
Cathern Its a hack but it works fine. Try it.
public static boolean hasSoftKeys(WindowManager windowManager){
Display d = windowManager.getDefaultDisplay();
DisplayMetrics realDisplayMetrics = new DisplayMetrics();
d.getRealMetrics(realDisplayMetrics);
int realHeight = realDisplayMetrics.heightPixels;
int realWidth = realDisplayMetrics.widthPixels;
DisplayMetrics displayMetrics = new DisplayMetrics();
d.getMetrics(displayMetrics);
int displayHeight = displayMetrics.heightPixels;
int displayWidth = displayMetrics.widthPixels;
return (realWidth - displayWidth) > 0 || (realHeight - displayHeight) > 0;
}
The accepted answer should work fine on most real devices, but it doesn't work in the emulators.
However, in Android 4.0 and above, there's an internal API that also works on the emulators: IWindowManager.hasNavigationBar(). You can access it using reflection:
/**
* Returns {@code null} if this couldn't be determined.
*/
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
@SuppressLint("PrivateApi")
public static Boolean hasNavigationBar() {
try {
Class<?> serviceManager = Class.forName("android.os.ServiceManager");
IBinder serviceBinder = (IBinder)serviceManager.getMethod("getService", String.class).invoke(serviceManager, "window");
Class<?> stub = Class.forName("android.view.IWindowManager$Stub");
Object windowManagerService = stub.getMethod("asInterface", IBinder.class).invoke(stub, serviceBinder);
Method hasNavigationBar = windowManagerService.getClass().getMethod("hasNavigationBar");
return (boolean)hasNavigationBar.invoke(windowManagerService);
} catch (ClassNotFoundException | ClassCastException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
Log.w("YOUR_TAG_HERE", "Couldn't determine whether the device has a navigation bar", e);
return null;
}
}
null
so you can detect when it didn't work. You need to decide what to do when that happens and add code for it. –
Apophysis Try this method,in this way you can detect if the navigation bar exist.
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public boolean hasNavBar(Context context) {
Point realSize = new Point();
Point screenSize = new Point();
boolean hasNavBar = false;
DisplayMetrics metrics = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getRealMetrics(metrics);
realSize.x = metrics.widthPixels;
realSize.y = metrics.heightPixels;
getWindowManager().getDefaultDisplay().getSize(screenSize);
if (realSize.y != screenSize.y) {
int difference = realSize.y - screenSize.y;
int navBarHeight = 0;
Resources resources = context.getResources();
int resourceId = resources.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
navBarHeight = resources.getDimensionPixelSize(resourceId);
}
if (navBarHeight != 0) {
if (difference == navBarHeight) {
hasNavBar = true;
}
}
}
return hasNavBar;
}
Right answer and other are not actual now.
There are exist some options like 'Full Screen Display -> Full Screen Gestures' where navigation bar is hidden but all this methods returns that he is present.
I suggest you to use this way to check size of system views. In onCreate method:
ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content),
(v, insets) -> {
int navigationBarHeight = insets.getSystemWindowInsetBottom();
return insets;
});
Other answers don't help me. But it's quite useful to know if navigation bar is shown, especially after Android P/Q, where user can swipe it out of screen. I've encounter this article https://blog.stylingandroid.com/gesture-navigation-window-insets/ and made such method
fun hasNavBar(activity: Activity): Boolean {
val temporaryHidden = activity.window.decorView.visibility and View.SYSTEM_UI_FLAG_HIDE_NAVIGATION != 0
if (temporaryHidden) return false
val decorView = activity.window.decorView
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
decorView.rootWindowInsets?.let{
return it.stableInsetBottom != 0
}
}
return true
}
The point of finding the soft navigation enabled or not is to determine what is the size of the window provided and to set the layout according to.
There is a very powerful tool called decorView
that sets the window from before so as to directly implement methods under it. It can be written like this:
val decorView = window.decorView
decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
Just start writing methods under it whichever you want to make inside the frame.
Found this one working after trying a ton of methods and tricks and this one is the only one working.
© 2022 - 2024 — McMap. All rights reserved.