检测Android导航栏方向

人生处万类,知识最为贤。这篇文章主要讲述检测Android导航栏方向相关的知识,希望能为你提供帮助。
有没有办法知道这个导航栏将在哪里显示为横向:

  • 在Nexus7上它位于底部
  • 在nexus 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;

另一答案部分基于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()的算法),任何关键的东西。
另一答案我的解决方案
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的解决方案
另一答案我的工作解决方案是:
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); }

另一答案这与我的应用程序一起使用,我使用半透明状态栏和导航栏来设置填充。
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
编辑:如果上面的给你0,获得这样的布局高度
@Override public void onWindowFocusChanged (boolean hasFocus) { // the height will be set at this point bkgHeight = bkg.getHeight(); }

另一答案请注意,从Android 7.1开始,导航栏也可能位于屏幕的左侧。为了确保您始终知道导航栏的位置,请使用DisplayListener检查Android 7.1及更高版本上的180°屏幕更改,如下所示:How to detect screen rotation through 180 degrees from landscape to landscape orientation?
【检测Android导航栏方向】我已成功并可靠地使用此代码来确定导航栏位置的任何更改:
DisplayManager.DisplayListener displayListener; @Override protected void onCreate(Bundle savedInstanceState) {...displayListener = new DisplayManager.DisplayListener() { private int lastRotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay().getRotation(); @Override public void onDisplayAdded(int displayId) { }@Override public void onDisplayChanged(int displayId) { int rotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)) .getDefaultDisplay().getRotation(); if (rotation == Surface.ROTATION_90 & & lastRotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_270 & & lastRotation == Surface.ROTATION_90) { onNavigationBarMoved(true); } lastRotation = rotation; }@Override public void onDisplayRemoved(int displayId) { } }; DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); displayManager.registerDisplayListener(displayListener, null); onNavigationBarMoved(false); }@Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); onNavigationBarMoved(false); }@Override protected void onDestroy() { if (displayListener != null) { DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); displayManager.unregisterDisplayListener(displayListener); } super.onDestroy(); }protected void onNavigationBarMoved(boolean lands

    推荐阅读