Есть ли способ узнать, где эта панель навигации будет отображаться пейзаж:Detect Android панель навигации ориентации
- на Nexus7 она находится в нижних
- на стыке 5 она находится справа.
Благодаря
Есть ли способ узнать, где эта панель навигации будет отображаться пейзаж:Detect Android панель навигации ориентации
Благодаря
Используя свойства 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;
Это может работать некорректно, если отображается мягкая клавиатура. Высота клавиатуры вычитается из кадра дисплея. – crazymaik
На Nexus 5 оба isRightOfContent и isBelowContent являются истинными –
Это работает с моим приложением, я использую это с полупрозрачной статусной и навигационной панели, чтобы установить отступы.
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();
}
Мое решение
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
, частично на основе ответа 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()
), для чего-то критического.
Привет CommonsWare. Будет ли это решение работать и для панели навигации? Кроме того, можете ли вы указать какой-то контекст на то, почему canMove необходимо? – sudocoder
@sudocoder: «Будет ли это решение работать и для панели навигации?» - Я не уверен, что вы рассматриваете как «навигационную панель». Этот термин не использовался с Honeycomb, IIRC. «Почему canMove нужен?» - потому что на некоторых устройствах и версиях ОС системная панель меняет положение. – CommonsWare
«Панель навигации» Я имею в виду, на что указывают красные стрелки на фотографиях, предоставленных OP. Я займу некоторое время, чтобы разобраться "(! CanMove || dm.widthPixels
Рабочий раствор для меня:
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);
}
Имейте в виду, что, начиная с 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
Почему вы должны знать, что? –
[кнопка меню мертва] (http://android-developers.blogspot.com/2012/01/say-goodbye-to-menu-button.html). – ianhanniballake
Ни Nexus 7, ни Nexus 5 не имеют постоянной кнопки MENU. – CommonsWare