全面屏虛擬按鍵高度適配

需求場景: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
來源:掘金
著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章