These two ways are restricted by non-SDK interfaces restrictions(*reflection required*):
if you call PackageManager#getInstalledApplications
, you'll see some applications' package name contains "systemui.navbar", they belongs to Runtime Resource Overlay(RRO) packages which their isResourceOverlay()
returns true
. System use android.content.om.OverlayManager
to manage overlay packages and android.content.om.OverlayInfo
to get enable state.
use getResources().getInteger()
with com.android.internal.R$integer#config_navBarInteractionMode
to get
value android.view.WindowManagerPolicyConstants#NAV_BAR_MODE_*
so...
after several tries...
(Java)
gesture navigation maybe smaller than or equals to status bar normally, so if it's larger, i think it's 2/3-button.
based on API level 29
, see WindowInsets or compat.
//...
import android.graphics.Color;
import android.graphics.Insets;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowInsets$Type;
import android.os.Build;
//...
private boolean isAndroidR = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
view.setOnApplyWindowInsetsListener((View v, WindowInsets i) -> {
Insets inset = isAndroidR
//or getInsetsIgnoringVisibility
? i.getInsets(
Type.statusBars() | Type.navigationBars()
)
//or getStableInsets
: i.getSystemWindowInsets();
//some devices' height maybe 0
int status, navigation;
//the height difference of gesture navigation and notification bar is small
boolean isGestureNavigation =
//maybe 0 if hidden, use getInsetsIgnoringVisibility/getStableInsets
(status = inset.top) != 0 &&
//some system may provide an option to always hide gesture navigation, so always 0
(navigation = inset.bottom) != 0 &&
status >= navigation;
//do something
getWindow().setNavigationBarColor(
isGestureNavigation ? Color.TRANSPARENT : Color.BLUE
);
return i;//isAndroidR ? WindowInsets.CONSUMED : i.consumeSystemWindowInsets()
});
//...