需求場景:ScrollView中需要一個定高的recyclerView,其高度爲屏幕高度,本以爲一個簡單的需求,調試了半天.
最初的高度獲取
public static int getScreenHeight(Context context) {
final Resources resources = context.getResources();
final DisplayMetrics dm = resources.getDisplayMetrics();
return dm.heightPixels;
}
複製代碼測試結果(PS:測試機有限,歡迎更多人加入測試,發現未知的問題)
手機類型
getScreenHeight()
getRealHeight()
狀態欄
虛擬按鍵
Mi8虛擬按鍵模式
2120
2340
110
130
Mi8手勢模式
2120
2340
110
130
華爲Mate20虛擬按鍵模式
2094
2244
81
114
華爲Mate20手勢模式
2163
2244
81
114
vivo-z20虛擬按鍵模式
2154
2280
84
126
vivo-z20手勢模式
2280
2280
84
126
由測試可以看出,getScreenHeight()獲取的高度在各平臺是不統一的,原因也各異:
理論上 getScreenHeight()獲取的是可用高度,即屏幕整體高度減去佔用的狀態欄和虛擬按鍵.
小米不區分是否使用了虛擬按鍵.
華爲,手勢模式下正常,但虛擬按鍵模式高度有偏差.
vivo,獲取的高度多了狀態欄高度.
而獲取真實高度,狀態欄高度,虛擬按鍵高度,可以獲取一致的值,因此最終方案採用 真實高度- 狀態欄高度- 虛擬按鍵高度來獲取真實的可用高度(PS:由於現今絕大部分項目都不使用ActionBar,所以未考慮ActionBar的影響).
真實的可用高度獲取(真實全屏高度- 狀態欄高度- 虛擬按鍵高)
獲取真實高度
public static int getRealHeight(Context context) {
Display display = getDisplay(context);
if (display == null) {
return 0;
}
DisplayMetrics dm = new DisplayMetrics();
display.getRealMetrics(dm);
return dm.heightPixels;
}
複製代碼
狀態欄高度
public static int getStatusHeight() {
int height = 0;
int resourceId = Latte.getApplicationContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
if (resourceId > 0) {
height = Latte.getApplicationContext().getResources().getDimensionPixelSize(resourceId);
}
return height;
}
複製代碼
虛擬按鍵是否使用
檢測是否是全面屏模式,如果是,不需考慮虛擬鍵
檢測虛擬按鍵是否隱藏了
/**
* 非全面屏下 虛擬按鍵是否打開
*
* @param activity activity
* @return 虛擬按鍵是否打開
*/
private static boolean isNavigationBarShown(Activity activity) {
//虛擬鍵的view,爲空或者不可見時是隱藏狀態
View view = activity.findViewById(android.R.id.navigationBarBackground);
if (view == null) {
return false;
}
int visible = view.getVisibility();
if (visible == View.GONE || visible == View.INVISIBLE) {
return false;
} else {
return true;
}
}
/**
* 全面屏(是否開啓全面屏開關 0 關閉 1 開啓)
*
* @param context activity
* @return 是否是前面屏
*/
private static boolean navigationGestureEnabled(Context context) {
int val = Settings.Global.getInt(context.getContentResolver(), getDeviceInfo(), 0);
return val != 0;
}
複製代碼
虛擬按鍵高度
private static int getNavigationBarHeight(Context context) {
int result = 0;
int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0) {
result = context.getResources().getDimensionPixelSize(resourceId);
}
return result;
}
複製代碼
可用高度
有了上面這些信息,即可獲取真實的可用區域高度: getScreenHeightReal(context) - getStatusHeight() - getNavigationBarHeightIfRoom(context)
工具類路徑
相關知識(Display&&DisplayMetrics)
DisplayMetrics: 提供屏幕的通用信息,如顯示大小,分辨率和字體
Display:提供邏輯顯示區域大小、密度的相關信息
本次用的的方法
context.getResources().getDisplayMetrics(): 包含可視區域的屏幕信息的DisplayMetrics;
activity.getWindowManager().getDefaultDisplay(): 獲取當前屏幕信息的 Display;
display.getMetrics(DisplayMetrics outMetrics): 將dispay的可視區信息填入outMetics;
display.getRealMetrics(DisplayMetrics outMetrics) :將dispay的真實區域(即完整屏幕區域)信息填入outMetics;
作者:wangfengye
鏈接:https://juejin.cn/post/6844903829595504648
來源:掘金
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。