2015-03-11 4 views

Répondre

48

La méthode suivante a fonctionné pour moi et a testé dans beaucoup de dispositifs.

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

Note: vérifié cette méthode dans le dispositif réel

+1

Ce code fonctionne mais au lieu de 'android' utiliser '"android"' – BlueMango

+3

Renvoie 'false' dans les deux cas. – CoolMind

+1

Notez que ceci renvoie toujours 'false' sur les émulateurs Android. Voir [ce message de validation] (https://github.com/android/platform_frameworks_base/commit/0c4ccff36930ff4f0292b94ad51e164c9fa060a3) pour une explication. – Sam

15

Comme je sais que vous pouvez le détecter par

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

Mais il fallait API 14+


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

public boolean isNavigationBarAvailable(){ 

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

     return (!(hasBackKey && hasHomeKey)); 
    } 
+0

Merci pour votre réponse. Je cherche à déterminer la présence de barre de navigation douce. –

+0

L'appareil n'a pas de clé de menu permanente n'est pas égale à l'appareil ont une barre de navigation douce. Certains appareils n'ont pas de touche de menu permanente et ne possèdent pas de barre de navigation. S'il vous plaît regarder cet appareil http://www.gsmarena.com/asus_zenfone_5-pictures-5952.php –

+0

Merci pour cette excellente information, en raison de ce type d'appareils, vous pouvez essayer ma deuxième solution (chercher une réponse mise à jour) – IshRoid

9

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; 
} 
+0

D'accord que c'est un hack, mais un excellent. Kudos –

+0

merci cela a fonctionné –

2

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

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

} 
7

The accepted answer devrait fonctionner correctement sur la plupart des appareils réels, mais il ne fonctionne pas dans les émulateurs.

Toutefois, dans Android 4.0 et versions ultérieures, 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; 
    } 
} 
+0

Bien sûr, en utilisant l'API interne sorte de piqûres, mais bon, ça marche sur tous mes appareils (au moins jusqu'à API25). Extra + pour ne pas être dépendant du contexte. – nekavally

+0

cela fonctionne pour moi mais je reçois un avertissement à propos de je peux obtenir une exception de pointeur nul. Est-il sécuritaire d'utiliser? – Dahnark

+0

@Dahnark c'est une API interne, il n'y a donc aucune garantie qu'elle fonctionnera sur un périphérique donné. La méthode dans mon exemple retourne 'null' afin que vous puissiez détecter quand cela n'a pas fonctionné. Vous devez décider quoi faire quand cela arrive et ajouter du code pour cela. – Sam