Обнаружение ориентации навигационной панели Android
Есть ли способ узнать, где эта панель навигации будет отображаться для пейзажа:
- на Nexus7 находится внизу
- на узле 5 находится справа.
Спасибо
![enter image description here]()
Ответы
Ответ 1
Используя свойства вид декора в сочетании с текущим 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;
Ответ 2
Мое решение
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
Ответ 3
Основанный частично на ответе Павла (в свою очередь, на основе реализации 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()
), для чего-то критического.
Ответ 4
Рабочее решение для меня:
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);
}
Ответ 5
Это работает с моим приложением, я использую его с полупрозрачной панелью состояния и навигационной панелью, чтобы установить дополнение.
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, с некоторыми макетами, которые он мне дал 0
EDIT:
Получите высоту макета, как это, если приведенное выше дает вам 0
@Override
public void onWindowFocusChanged (boolean hasFocus) {
// the height will be set at this point
bkgHeight = bkg.getHeight();
}