2014-01-11 4 views
14

Есть ли способ узнать, где эта панель навигации будет отображаться пейзаж:Detect Android панель навигации ориентации

  • на Nexus7 она находится в нижних
  • на стыке 5 она находится справа.

Благодаря

enter image description here

+2

Почему вы должны знать, что? –

+0

[кнопка меню мертва] (http://android-developers.blogspot.com/2012/01/say-goodbye-to-menu-button.html). – ianhanniballake

+0

Ни Nexus 7, ни Nexus 5 не имеют постоянной кнопки MENU. – CommonsWare

ответ

5

Используя свойства decor view в сочетании с текущей DisplayMetrics вы можете узнать, на какой стороне панели навигации расположена.

// retrieve the position of the DecorView 
Rect visibleFrame = new Rect(); 
getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleFrame); 

DisplayMetrics dm = getResources().getDisplayMetrics(); 
// check if the DecorView takes the whole screen vertically or horizontally 
boolean isRightOfContent = dm.heightPixels == visibleFrame.bottom; 
boolean isBelowContent = dm.widthPixels == visibleFrame.right; 
+0

Это может работать некорректно, если отображается мягкая клавиатура. Высота клавиатуры вычитается из кадра дисплея. – crazymaik

+2

На Nexus 5 оба isRightOfContent и isBelowContent являются истинными –

1

Это работает с моим приложением, я использую это с полупрозрачной статусной и навигационной панели, чтобы установить отступы.

boolean navBarOnTheBottom(){ 
     DisplayMetrics displaymetrics = new DisplayMetrics(); 
     getWindowManager().getDefaultDisplay().getMetrics(displaymetrics); 
     int viewHeight = displaymetrics.heightPixels; 
     if (bkg.getHeight() == viewHeight) 
     { 
      Log.d(TAG, "nav bar on the side"); 
      return false; 
     } 
     else{ 
      Log.d(TAG, "nav bar on the bottom"); 
      return true; 
     } 
    } 

bkg это основной linearLayout, который содержит все мои приложения. Убедитесь, что bkg.getHeight() не дает 0, с некоторыми раскладками она дает мне-

EDIT: Получить высоту макета, как это, если выше один дает 0

@Override 
    public void onWindowFocusChanged (boolean hasFocus) { 
     // the height will be set at this point 
     bkgHeight = bkg.getHeight(); 
    } 
5

Мое решение

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

public static int getNavigationBarHeight (Resources resources) 
{ 
    if (!Utils.hasNavBar(resources)) 
     return 0; 

    int orientation = resources.getConfiguration().orientation; 

    //Only phone between 0-599 has navigationbar can move 
    boolean isSmartphone = resources.getConfiguration().smallestScreenWidthDp < 600; 
    if (isSmartphone && Configuration.ORIENTATION_LANDSCAPE == orientation) 
     return 0; 

    int id = resources 
     .getIdentifier(orientation == Configuration.ORIENTATION_PORTRAIT ? "navigation_bar_height" : "navigation_bar_height_landscape", "dimen", "android"); 
    if (id > 0) 
     return resources.getDimensionPixelSize(id); 

    return 0; 
} 

public static int getNavigationBarWidth (Resources resources) 
{ 
    if (!Utils.hasNavBar(resources)) 
     return 0; 

    int orientation = resources.getConfiguration().orientation; 

    //Only phone between 0-599 has navigationbar can move 
    boolean isSmartphone = resources.getConfiguration().smallestScreenWidthDp < 600; 

    if (orientation == Configuration.ORIENTATION_LANDSCAPE && isSmartphone) 
    { 
     int id = resources.getIdentifier("navigation_bar_width", "dimen", "android"); 
     if (id > 0) 
      return resources.getDimensionPixelSize(id); 
    } 

    return 0; 
} 

решение основано на https://android.googlesource.com/platform/frameworks/base/+/9f65c4c34abb07bdda54649ed510af26f16e9c1b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java

4

, частично на основе ответа Pauland (в свою очередь, на основе реализации PhoneWindowManager), вот что я использую в данный момент:

public static boolean isSystemBarOnBottom(Context ctxt) { 
    Resources res=ctxt.getResources(); 
    Configuration cfg=res.getConfiguration(); 
    DisplayMetrics dm=res.getDisplayMetrics(); 
    boolean canMove=(dm.widthPixels != dm.heightPixels && 
     cfg.smallestScreenWidthDp < 600); 

    return(!canMove || dm.widthPixels < dm.heightPixels); 
    } 

Это работает на Nexus 7 2012 и Nexus 4, каждое из которых работает Android 5.1.

На устройствах с постоянной клавишей MENU нет системной панели. В зависимости от вашего случая использования, возможно, потребуется проверить для этого случая:

ViewConfiguration.get(ctxt).hasPermanentMenuKey() 

(где ctxt есть некоторые Context)

Лично я использую это, чтобы попытаться иметь скользящую панель находиться на противоположном оси от панели системы, так как окантовка сбоку со стороны с системной панелью немного затруднительна. Я бы не использовал это или какой-либо другой алгоритм (например, тот, который зависит от getDecorView()), для чего-то критического.

+0

Привет CommonsWare. Будет ли это решение работать и для панели навигации? Кроме того, можете ли вы указать какой-то контекст на то, почему canMove необходимо? – sudocoder

+0

@sudocoder: «Будет ли это решение работать и для панели навигации?» - Я не уверен, что вы рассматриваете как «навигационную панель». Этот термин не использовался с Honeycomb, IIRC. «Почему canMove нужен?» - потому что на некоторых устройствах и версиях ОС системная панель меняет положение. – CommonsWare

+0

«Панель навигации» Я имею в виду, на что указывают красные стрелки на фотографиях, предоставленных OP. Я займу некоторое время, чтобы разобраться "(! CanMove || dm.widthPixels sudocoder

3

Рабочий раствор для меня:

public static boolean hasNavBar(Context context) { 
     WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
     Point realPoint = new Point(); 
     Display display = wm.getDefaultDisplay(); 
     display.getRealSize(realPoint); 
     DisplayMetrics metrics = new DisplayMetrics(); 
     wm.getDefaultDisplay().getMetrics(metrics); 
     return metrics.heightPixels + metrics.widthPixels != realPoint.y + realPoint.x; 
    } 

    public static boolean isSystemBarOnBottom(Context context) { 
     WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
     Point realPoint = new Point(); 
     Display display = wm.getDefaultDisplay(); 
     display.getRealSize(realPoint); 
     DisplayMetrics metrics = new DisplayMetrics(); 
     wm.getDefaultDisplay().getMetrics(metrics); 
     Configuration cfg = context.getResources().getConfiguration(); 
     boolean canMove = (metrics.widthPixels != metrics.heightPixels && 
       cfg.smallestScreenWidthDp < 600); 

     return (!canMove || metrics.widthPixels < metrics.heightPixels); 
    } 
0

Имейте в виду, что, начиная с Android 7.1 панель навигации также может быть расположен на левой стороне экрана. Чтобы убедиться, что вы всегда знаете положение навигационной панели, используйте DisplayListener, чтобы проверить изменения экрана на 180 ° на Android 7.1 и выше, как здесь: How to detect screen rotation through 180 degrees from landscape to landscape orientation?

Внутри onDisplayChanged и onConfigurationChanged, этот код будет сообщать вам, если панель навигации находится на левой стороне:

boolean leftSideNavigationBar = Build.VERSION.SDK_INT > Build.VERSION_CODES.N 
          && ((WindowManager) getSystemService(Context.WINDOW_SERVICE)) 
            .getDefaultDisplay().rotation == Surface.ROTATION_270 
Смежные вопросы