判斷全面屏是否有虛擬導航欄的方法isNavigationBarExist是無效的,搜索了不少方法都不生效,緣由目前未知,猜想多是定製ROM並無按照標準的系統設置,而是各廠家使用了本身的處理java
安卓設備在一些屏幕適應計算中一般須要獲取屏幕的高度。在非全面屏的設備中,獲取屏幕高度可使用下面的方法,能夠獲取到包含屏幕頂部通知欄但不包含底部虛擬導航欄的屏幕高度:android
DisplayMetrics dm = context.getResources().getDisplayMetrics();
int w = dm.widthPixels;
int h = dm.heightPixels;
if (w < h)
return h;
else
return w;
複製代碼
可是,在全面屏設備中這個方法是不能正常工做的,獲取到的屏幕高度比實際屏幕高度要小,填充後底部會出現一個黑色的矩形區域。解決的方法是使用下面的方法獲取一個全屏幕的高度,包含頂部通知欄又包含底部虛擬導航欄的屏幕高度:ui
WindowManager windowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getRealMetrics(metrics);
int w = metrics.widthPixels;
int h = metrics.heightPixels;
if (w < h)
return h;
else
return w;
複製代碼
這個計算結果和方法一相比,多了底部虛擬導航欄的高度,這就須要減去它,使得兩種結果所獲取到的高度包含的區域相同。spa
int getVirtualNavigationBarHeight(Context context) {
int result = 0;
if (isNavigationBarExist(context)) {
int resourceId =context.getResources().getIdentifier("navigation_bar_height","dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
}
return result;
}
boolean isNavigationBarExist(@NonNull Context context) {
if ("HUAWEI".equals(Build.BRAND) || "HONOR".equals(Build.BRAND)){
return isNavigationBarShow_HUIWEI(context);
}
return KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
}
boolean isNavigationBarShow_HUIWEI(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1){
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = windowManager.getDefaultDisplay();
Point size = new Point();
Point realSize = new Point();
display.getSize(size);
display.getRealSize(realSize);
return realSize.y != size.y;
} else {
boolean menu = ViewConfiguration.get(context).hasPermanentMenuKey();
boolean back = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
if (menu || back) {
return false;
} else {
return true;
}
}
}
複製代碼
int getRawDeviceScreenHeight(@NonNull Context context) {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
windowManager.getDefaultDisplay().getRealMetrics(metrics);
int navBarHeight = getVirtualNavigationBarHeight(context);
int w = metrics.widthPixels;
int h = metrics.heightPixels;
if (w < h)
return h - navBarHeight;
else
return w - navBarHeight;
}
複製代碼
兩個方法都有了,可是咱們要對使用場景作一個選擇,還須要判斷手機是不是全面屏,判斷全面屏根據是屏幕的高/寬值,這裏設定閾值爲1.97:code
boolean isAllScreenDevice(Context context) {
// 低於 API 21的,都不會是全面屏。。。
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return false;
}
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
if (windowManager != null) {
Display display = windowManager.getDefaultDisplay();
Point point = new Point();
display.getRealSize(point);
float width, height;
if (point.x < point.y) {
width = point.x;
height = point.y;
} else {
width = point.y;
height = point.x;
}
if (height / width >= 1.97f) {
return true;
}
}
return false;
}
複製代碼
綜上,獲取安卓屏幕高度的方法爲:資源
int getDeviceScreenHeight(@NonNull Context context) {
if (context == null) {
return 1;
}
if (isAllScreenDevice(context)) {
return getRawDeviceScreenHeight(context);
}
DisplayMetrics dm = context.getResources().getDisplayMetrics();
int w = dm.widthPixels;
int h = dm.heightPixels;
if (w < h)
return h;
else
return w;
}
複製代碼
若是還須要減去頂部通知欄的高度的話,這裏給出獲取頂部通知欄高度的方法:get
int getStatusBarHeight(@NonNull Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
複製代碼
參考文章: android 獲取虛擬鍵盤高度string