【问题标题】:getSize() deprecated in API level 30getSize() 在 API 级别 30 中已弃用
【发布时间】:2020-12-22 10:15:24
【问题描述】:

我使用 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()来获取屏幕尺寸?

感谢您的任何评论/回答!

解决方案

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
}

【问题讨论】:

    标签: android deprecation-warning android-api-levels


    【解决方案1】:

    新的Jetpack WindowManager library 为新旧平台版本中的新窗口管理器功能(例如可折叠设备和 Chrome 操作系统)提供了一个通用 API 界面。

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

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

    异步 WindowMetrics 流:

    当窗口大小发生变化时,使用WindowInfoRepository#currentWindowMetrics 得到库的通知,与此更改是否会触发配置更改无关。

    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()
            }
    }
    

    同步 WindowMetrics:

    在异步 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

    【讨论】:

    • import androidx.window.WindowManager 似乎不存在
    • WindowManagerv1.0.0-alpha10 中被删除,取而代之的是WindowInfoRepositoryWindowMetricsCalculator。我刚刚更新了答案。谢谢。
    【解决方案2】:

    如果你像我一样,只是想获取窗口大小,这里有一个兼容的版本:

    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)
            }
        }
    }
    

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

    【讨论】:

      【解决方案3】:

      "使用WindowManager#getCurrentWindowMetrics()获取实例 WindowMetrics 并改用 WindowMetrics#getBounds()。”

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-12-24
        • 2020-11-09
        • 2022-08-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-08
        相关资源
        最近更新 更多