Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting screen width on API Level 30 (Android 11): getDefaultDisplay() and getMetrics() are now deprecated. What should we use instead?

I currently calculate the screen width like this :

public static int getScreenWidth(@NonNull Context context) {
    DisplayMetrics displayMetrics = new DisplayMetrics();
    ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
    return displayMetrics.widthPixels;
}

Since these 2 functions (getDefaultDisplay() and getMetrics()) are now deprecated, what should we use instead ?

like image 743
Denis Avatar asked Aug 14 '20 06:08

Denis


3 Answers

For calculating screen width minus any system bars, this should work:

public static int getScreenWidth(@NonNull Activity activity) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();
        Insets insets = windowMetrics.getWindowInsets()
                .getInsetsIgnoringVisibility(WindowInsets.Type.systemBars());
        return windowMetrics.getBounds().width() - insets.left - insets.right;
    } else {
        DisplayMetrics displayMetrics = new DisplayMetrics();
        activity.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        return displayMetrics.widthPixels;
    }
}

Note that this isn't exactly the same: testing this with the height produces different results, and I've been unable to replicate the old API's functionality with the new API (partly due to the behavior of the old API being a bit tricky to reason about and not always what you want, hence its deprecation). In practice, though, it should be good enough as a generic screen width for many things.

like image 51
Ryan M Avatar answered Oct 06 '22 12:10

Ryan M


@RequiresApi(20)
inline val Fragment.windowHeight: Int
    get() {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val metrics = requireActivity().windowManager.currentWindowMetrics
            val insets = metrics.windowInsets.getInsets(WindowInsets.Type.systemBars())
            metrics.bounds.height() - insets.bottom - insets.top
        } else {
            val view = requireActivity().window.decorView
            val insets = WindowInsetsCompat.toWindowInsetsCompat(view.rootWindowInsets, view).getInsets(WindowInsetsCompat.Type.systemBars())
            resources.displayMetrics.heightPixels - insets.bottom - insets.top
        }
    }

@RequiresApi(20)
inline val Fragment.windowWidth: Int
    get() {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            val metrics = requireActivity().windowManager.currentWindowMetrics
            val insets = metrics.windowInsets.getInsets(WindowInsets.Type.systemBars())
            metrics.bounds.width() - insets.left - insets.right
        } else {
            val view = requireActivity().window.decorView
            val insets = WindowInsetsCompat.toWindowInsetsCompat(view.rootWindowInsets, view).getInsets(WindowInsetsCompat.Type.systemBars())
            resources.displayMetrics.widthPixels - insets.left - insets.right
        }
    }

This requires androidx.core version 1.5.x

like image 9
Vincent Joshua Tigas Avatar answered Oct 06 '22 10:10

Vincent Joshua Tigas


Running into the same problem in 2022, there's a newish Jetpack library for handling this across the various API versions.

build.gradle

dependencies {
    implementation 'androidx.window:window:1.0.0'

}
import androidx.window.layout.WindowMetrics;
import androidx.window.layout.WindowMetricsCalculator;


WindowMetrics windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity);
final int height = windowMetrics.getBounds().height();
final int width = windowMetrics.getBounds().width();

One caveat I ran into as well is that including androidx.window ended up pulling in tens of thousands of library methods that put me above the DEX 64k method limit, so I had to figure out how optimize those out using the R8/proguard settings, but that's another problem.

like image 6
dragonx Avatar answered Oct 06 '22 12:10

dragonx