Android獲取屏幕寬、高、狀態欄高度、導航欄高度、是否是全面屏

獲取屏幕的可使用高度

最近在做屏幕高度適配的時候,發現了一些問題,即我需要獲得下圖區域的高度的像素大小,如圖分析就是獲取屏幕的可使用高度,但是在兼容全面屏和非全面屏的時候,發現兩種機型的計算方式是有區別的。

image

爲了解決這個問題,我用兩種方法計算了全面屏(有導航欄、無導航欄)和非全面屏的高度:

/**
 * 獲取屏幕高度
 * 第一種,讀取DisplayMetrics的heightPixels參數
 */
private fun getScreenHeight(context: Context): Int {
    return context.resources?.displayMetrics?.heightPixels ?: 0
}

/**
 * 獲取屏幕Real高度
 * 第二種,讀取windowManager裏面的defaultDisplay參數
 */
@Volatile
private var sRealSizes = arrayOfNulls<Point>(2)
private fun getScreenRealHeight(context: Context): Int {
    var orientation = context.resources?.configuration?.orientation
    orientation = if (orientation == 1) 0 else 1
    if (sRealSizes[orientation] == null) {
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val display = windowManager.defaultDisplay
        val point = Point()
        display.getRealSize(point)
        sRealSizes[orientation] = point
    }
    return sRealSizes[orientation]?.y ?: getScreenRealHeight(context)
}

機型1:非全面屏有導航欄

可以看到手機的實際高度是1920,但是由於有導航欄,導致可使用高度變成了1794,可見我們可以通過方法一getScreenHeight方法獲取可使用高度。

image

機型2:非全面屏無導航欄

這個手機實際高度也是1920,而且沒有導航欄,所以我們通過getScreenHeight方法獲取到可使用高度也是1920。由此可知非全面屏是可以通過這個方法獲取屏幕的可使用高度。

image

機型3:全面屏

可以發現屏幕實際高度是2340,但是通過getScreenHeight獲取到的高度是2135,很明顯是不對的,所以我們不能通過getScreenHeight方法獲取屏幕的可使用高度,而要通過getScreenRealHeight方法獲取。

image

綜上,我們可以通過以下方法來獲取屏幕的可使用高度,判斷全面屏的代碼我在後面給出:

if (DeviceUtils.isAllScreenDevice()) {
    // 全面屏要通過這個方法獲取高度
    screenHeight = DisplayUtils.getScreenRealHeight(getContext());
} else {
    screenHeight = DisplayUtils.getScreenHeight(getContext());
}

獲取屏幕寬度

 private fun getScreenWidth(context: Context): Int {
    return context.resources?.displayMetrics?.widthPixels ?: 0
}

private fun getScreenRealWidth(context: Context): Int {
    var orientation = context.resources?.configuration?.orientation
    orientation = if (orientation == 1) 0 else 1
    if (sRealSizes[orientation] == null) {
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val display = windowManager.defaultDisplay
        val point = Point()
        display.getRealSize(point)
        sRealSizes[orientation] = point
    }
    return sRealSizes[orientation]?.x ?: getScreenWidth(context)
}

獲取狀態欄高度

private fun getStatusBarHeight(window: Window, context: Context): Int {
    val localRect = Rect()
    window.decorView.getWindowVisibleDisplayFrame(localRect)
    var mStatusBarHeight = localRect.top
    if (0 == mStatusBarHeight) {
        try {
            val localClass = Class.forName("com.android.internal.R\$dimen")
            val localObject = localClass.newInstance()
            val i5 =
                localClass.getField("status_bar_height")[localObject].toString().toInt()
            mStatusBarHeight = context.resources.getDimensionPixelSize(i5)
        } catch (var6: ClassNotFoundException) {
            var6.printStackTrace()
        } catch (var7: IllegalAccessException) {
            var7.printStackTrace()
        } catch (var8: InstantiationException) {
            var8.printStackTrace()
        } catch (var9: NumberFormatException) {
            var9.printStackTrace()
        } catch (var10: IllegalArgumentException) {
            var10.printStackTrace()
        } catch (var11: SecurityException) {
            var11.printStackTrace()
        } catch (var12: NoSuchFieldException) {
            var12.printStackTrace()
        }
    }
    if (0 == mStatusBarHeight) {
        val resourceId: Int =
            context.resources.getIdentifier("status_bar_height", "dimen", "android")
        if (resourceId > 0) {
            mStatusBarHeight = context.resources.getDimensionPixelSize(resourceId)
        }
    }
    return mStatusBarHeight
}

獲取導航欄高度

 private fun getNavigationBarHeight(context: Context): Int {
    val rid: Int =
        context.resources.getIdentifier("config_showNavigationBar", "bool", "android")
    return if (rid != 0) {
        val resourceId: Int =
            context.resources.getIdentifier("navigation_bar_height", "dimen", "android")
        context.resources.getDimensionPixelSize(resourceId)
    } else {
        0
    }
}

是否全面屏

private fun isAllScreenDevice(context: Context): Boolean {
    if (VERSION.SDK_INT < 21) {
        return false
    } else {
        val windowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
        val display = windowManager.defaultDisplay
        val point = Point()
        display.getRealSize(point)
        val width: Float
        val height: Float
        if (point.x < point.y) {
            width = point.x.toFloat()
            height = point.y.toFloat()
        } else {
            width = point.y.toFloat()
            height = point.x.toFloat()
        }
        if (height / width >= 1.97f) {
            return true
        }
        return false
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章