web-dev-qa-db-fra.com

Détecter la disponibilité de la barre de navigation douce dans Android appareil par programmation?

J'essaie de déterminer la barre de navigation douce via le programme Android. Je n'ai pas trouvé de moyen direct de déterminer. Y a-t-il de toute façon pour trouver la disponibilité de la barre de navigation.

L'image de la barre de navigation douce est ici.

enter image description here

29
Raghu Rami Reddy

La méthode suivante a fonctionné pour moi et a été testée sur de nombreux appareils.

public boolean hasNavBar (Resources resources)
    {
        int id = resources.getIdentifier("config_showNavigationBar", "bool", "Android");
        return id > 0 && resources.getBoolean(id);
    }

Remarque: Vérifié cette méthode dans un appareil réel

66
Raghu Rami Reddy

Comme je sais, vous pouvez le détecter en

boolean hasSoftKey = ViewConfiguration.get(context).hasPermanentMenuKey();

Mais il fallait des API 14 +


Si la solution ci-dessus ne fonctionne pas pour vous, essayez la méthode ci-dessous

public boolean isNavigationBarAvailable(){

        boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
        boolean hasHomeKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_HOME);

        return (!(hasBackKey && hasHomeKey));
    }
22
IshRoid

C'est un hack mais ça marche bien. Essayez-le.

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;
}
14
Noman Rafique

La réponse acceptée devrait fonctionner correctement sur la plupart des appareils réels, mais cela ne fonctionne pas dans les émulateurs.

Cependant, dans Android 4.0 et supérieur, il existe une API interne qui fonctionne également sur les émulateurs: IWindowManager.hasNavigationBar () . Vous pouvez y accéder en utilisant la réflexion:

/**
 * 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;
    }
}
7
Sam

Essayez cette méthode, de cette façon, vous pouvez détecter si la barre de navigation existe.

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

}
2
Riccardo

D'autres réponses ne m'aident pas. Mais il est très utile de savoir si la barre de navigation s'affiche, en particulier après Android P/Q, où l'utilisateur peut le faire glisser hors de l'écran. J'ai rencontré cet article https://blog.stylingandroid.com/gesture-navigation-window-insets/ et fait une telle méthode

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
}
0
parmakli

La bonne réponse et d'autres ne sont pas réelles actuellement.
.

Je vous suggère d'utiliser cette méthode pour vérifier la taille des vues système. Dans la méthode onCreate:

ViewCompat.setOnApplyWindowInsetsListener(findViewById(Android.R.id.content), 
  (v, insets) -> { 
      int navigationBarHeight = insets.getSystemWindowInsetBottom();
      return insets;
  });
0
Dmitriy Puchkov