alexrnov
alexrnov

Reputation: 2534

getSize() deprecated in API level 30

I used the getSize() method to get the screen sizes:

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

But with API level 30 the method getSize() is declared deprecated.

What can be used instead of getSize() for obtain screen sizes?

Thank you for any comment/answer!

Solution:

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
}

Upvotes: 13

Views: 14227

Answers (3)

kirill21
kirill21

Reputation: 108

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

It's from Android documentation. [Android doc] https://developer.android.com/reference/android/view/Display#getSize(android.graphics.Point)

Upvotes: 4

David Miguel
David Miguel

Reputation: 14470

The new Jetpack WindowManager library provides a common API surface for new Window Manager features (e.g. foldable devices and Chrome OS) throughout old and new platform versions.

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

Jetpack WindowManager offers two ways to retrieve WindowMetrics information, as an asynchronous stream or synchronously.

Asynchronous WindowMetrics flow:

Use WindowInfoRepository#currentWindowMetrics to get notified by the library when there’s a window size change, independent of whether this change fires a configuration change.

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

Synchronous WindowMetrics:

Use WindowMetricsCalculator when writing code in a view where the asynchronous API can be too hard to deal with (such as onMeasure or during testing).

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

Ref: Unbundling the WindowManager | Android Developers Medium

Upvotes: 9

sokarcreative
sokarcreative

Reputation: 526

If like me, you just want to get the window size, here is a compat version :

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

it will take care of removing insets of navigation bars and display cutout areas to get the same result in both case

Upvotes: 9

Related Questions