安卓設備高度計算方法

判斷全面屏是否有虛擬導航欄的方法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

相關文章
相關標籤/搜索