getSize() 在 API 级别 30 中已弃用

getSize() deprecated in API level 30

我使用 getSize() 方法获取屏幕尺寸:

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val fragmentActivity = requireActivity()
    ...
    val wm = fragmentActivity.getSystemService(Context.WINDOW_SERVICE) as WindowManager 
    val display = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        fragmentActivity.display
    } else {
        wm.defaultDisplay 
    }
    val size = Point()
    display?.getSize(size)
    
    // get screen sizes
    val width = size.x
    val height = size.y
    ...
}

但是在 API 级别 30 中,方法 getSize() 被声明为已弃用。

可以使用什么代替 getSize() 来获取屏幕尺寸?

感谢您的任何 comment/answer!

解决方法:

val wm = fragmentActivity.getSystemService(Context.WINDOW_SERVICE) as WindowManager
val width: Int
val height: Int
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
    val windowMetrics = wm.currentWindowMetrics
    val windowInsets: WindowInsets = windowMetrics.windowInsets

    val insets = windowInsets.getInsetsIgnoringVisibility(
          WindowInsets.Type.navigationBars() or WindowInsets.Type.displayCutout())
    val insetsWidth = insets.right + insets.left
    val insetsHeight = insets.top + insets.bottom

    val b = windowMetrics.bounds
    width = b.width() - insetsWidth
    height = b.height() - insetsHeight
} else {
    val size = Point()
    val display = wm.defaultDisplay // deprecated in API 30
    display?.getSize(size) // deprecated in API 30
    width = size.x
    height = size.y
}

"Use WindowManager#getCurrentWindowMetrics() to obtain an instance of WindowMetrics and use WindowMetrics#getBounds() instead."

它来自 Android 文档。你读过吗? [Android 文档] https://developer.android.com/reference/android/view/Display#getSize(android.graphics.Point)

如果像我一样,您只想获得 window 尺码,这里有一个兼容版本:

fun WindowManager.currentWindowMetricsPointCompat(): Point {
    return if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
        val windowInsets = currentWindowMetrics.windowInsets
        var insets: Insets = windowInsets.getInsets(WindowInsets.Type.navigationBars())
        windowInsets.displayCutout?.run {
            insets = Insets.max(insets, Insets.of(safeInsetLeft, safeInsetTop, safeInsetRight, safeInsetBottom))
        }
        val insetsWidth = insets.right + insets.left
        val insetsHeight = insets.top + insets.bottom
        Point(currentWindowMetrics.bounds.width() - insetsWidth, currentWindowMetrics.bounds.height() - insetsHeight)
    }else{
        Point().apply {
            defaultDisplay.getSize(this)
        }
    }
}

它将负责删除导航栏的插入和显示切口区域,以便在两种情况下获得相同的结果

新的 Jetpack WindowManager library 为新的 Window 管理器功能(例如可折叠设备和 Chrome OS)提供了一个通用的 API 表面,贯穿新旧平台版本。

dependencies {
    implementation "androidx.window:window:1.0.0-beta02"
}

Jetpack WindowManager 提供两种检索 WindowMetrics 信息的方法,作为异步流或同步。

异步Window指标流:

使用 WindowInfoRepository#currentWindowMetrics 在 window 大小更改时得到库的通知,与此更改是否触发配置更改无关。

import androidx.window.layout.WindowInfoRepository
import androidx.window.layout.WindowInfoRepository.Companion.windowInfoRepository
import androidx.window.layout.WindowMetrics
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.flowWithLifecycle

lifecycleScope.launch(Dispatchers.Main) {
    windowInfoRepository().currentWindowMetrics.flowWithLifecycle(lifecycle)
        .collect { windowMetrics: WindowMetrics ->
           val currentBounds = windowMetrics.bounds // E.g. [0 0 1350 1800]
           val width = currentBounds.width()
           val height = currentBounds.height()
        }
}

同步Window指标:

在异步 API 难以处理的视图中编写代码时使用 WindowMetricsCalculator(例如 onMeasure 或在测试期间)。

import androidx.window.layout.WindowMetricsCalculator
import androidx.window.layout.WindowMetrics

val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity)
val currentBounds = windowMetrics.bounds // E.g. [0 0 1350 1800]
val width = currentBounds.width()
val height = currentBounds.height()

参考:Unbundling the WindowManager | Android Developers Medium