0

How can I determine the type of system navigation being used (gesture navigation or 2-/3-key navigation)? I want to add a background color for a certain type of system navigation.

val view = LocalView.current 
val window = (view.context as Activity).window

if (!view.isInEditMode) { 
    SideEffect {
        window.statusBarColor = Color.Transparent.toArgb()
        window.navigationBarColor = Color.Transparent.toArgb() // TODO

        WindowCompat.getInsetsController(window, view).apply {
            isAppearanceLightStatusBars = !darkTheme
            isAppearanceLightNavigationBars = !darkTheme
        }
    }
}
pie
  • 127
  • 9
  • Does this answer your question? [How can app get the mode of the navigation bar](https://stackoverflow.com/questions/68813787/how-can-app-get-the-mode-of-the-navigation-bar) – Tatsuya Fujisaki May 16 '23 at 12:36

1 Answers1

0

These two ways are restricted by non-SDK interfaces restrictions(*reflection required*):

  1. 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.

  2. 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()
});

//...
Ayaka_Ago
  • 89
  • 9