Getting screen size not from Activity subclass
Asked Answered
A

5

9

I have a view subclass that starts from activity subclass like that:

this.setContentView(instanceOfMyView);

In that my view subclass I want to make some work with screen size, but all people here says that it should be started like:

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm); 
screenWidth = dm.widthPixels;
screenHeight = dm.heightPixels; 

But getWindowManager() is the method that can be called from activity subclass only (Am I right?)

So, is it bad idea and I need to get screen size in activity and use it as parameters in view constructor or there is a way to get screen size in view subclass? Maybe, just need to somehow get a link to instance of activity in view class?

Thanks in advance.

Attenuation answered 26/7, 2012 at 12:47 Comment(0)
T
34

Yes there is a way, if you can pass the Context Object to your non activity class,

   int width= context.getResources().getDisplayMetrics().widthPixels;
   int height= context.getResources().getDisplayMetrics().heightPixels;

You don't need the Activity Object itself.

Triphibious answered 26/7, 2012 at 12:52 Comment(2)
Perfect, I already had context object in constructor of view subclass. Thanks.Attenuation
This doesn't return the screen resolution. Only what's available after subtracting the various system barsKnotweed
W
4
DisplayMetrics metrics = getBaseContext().getResources().getDisplayMetrics();         
    final int w = metrics.widthPixels;
    final int h = metrics.heightPixels;
Whore answered 26/7, 2012 at 12:56 Comment(2)
Seems to be that getBaseContext() is not working in view subclass, but just getContext() worked.Attenuation
This doesn't return the screen resolution. Only what's available after subtracting the various system barsKnotweed
K
1

The other answers here won't give you the screen resolution.

Here's how you should do it:

@SuppressLint("ObsoleteSdkInt")
@JvmStatic
fun getScreenResolution(context: Context, naturalResolution: Boolean = false): Point {
    val screenResolution = Point()
    val display = getDisplay(context)!!
    @Suppress("DEPRECATION")
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
        display.getRealSize(screenResolution)
    } else display.getSize(screenResolution)
    if (naturalResolution) {
        val screenNaturalOrientation = getScreenNaturalOrientation(context)
        if ((screenNaturalOrientation == Configuration.ORIENTATION_PORTRAIT && screenResolution.x > screenResolution.y)
                || (screenNaturalOrientation == Configuration.ORIENTATION_LANDSCAPE && screenResolution.y > screenResolution.x))
            screenResolution.set(screenResolution.y, screenResolution.x)
    }
    return screenResolution
}

/**
 * returns the natural orientation of the device: Configuration.ORIENTATION_LANDSCAPE or Configuration.ORIENTATION_PORTRAIT .<br></br>
 * The result should be consistent no matter the orientation of the device
 */
fun getScreenNaturalOrientation(context: Context): Int {
    //based on : https://mcmap.net/q/36886/-how-to-check-device-natural-default-orientation-on-android-i-e-get-landscape-for-e-g-motorola-charm-or-flipout
    val config = context.resources.configuration
    val rotation = getDisplay(context)!!.rotation
    return if ((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
            config.orientation == Configuration.ORIENTATION_LANDSCAPE
            || (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
            config.orientation == Configuration.ORIENTATION_PORTRAIT) Configuration.ORIENTATION_LANDSCAPE else Configuration.ORIENTATION_PORTRAIT
}

To get the display, use:

fun getDisplay(context: Context): Display? {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
        try {
            val result = context.display
            if (result != null)
                return result
        } catch (e: Throwable) {
        }
    if (context is Activity) {
        return try {
            @Suppress("DEPRECATION")
            context.windowManager.defaultDisplay
        } catch (e: Throwable) {
            null
        }
    }
    return null
}

docs:

https://developer.android.com/reference/android/view/Display.html#getRealSize(android.graphics.Point)

Knotweed answered 12/7, 2018 at 14:27 Comment(5)
As of API 30, WindowManager#getDefaultDisplay() is deprecated. What is the new intended way of getting the display associated with a WindowManager? Does context have to be an activity context, or can it be an application context?Devest
Also, getRealSize() is sensitive to device orientation. How can we get either the true width/height in portrait mode or in the device's natural orientation say?Devest
@Devest Was quite an old solution. I've now updated. Please let me know if it seems to work well now.Knotweed
I'm using java in my project, but I examined the updated kotlin code in detail and it seems to be correct, thanks. To answer my own question above, using an application context can work, but it is not intended and StrictMode gives you a fat red warning if you do it (getDisplay() from a non-visual context in java).Devest
Couldn't the natural resolution bit just be (?): if(naturalResolution) { val rotation = getDisplay(context)!!.rotation if(rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) screenResolution.set(screenResolution.y, screenResolution.x) } But great to also have that getScreenNaturalOrientation function in the utility belt.Devest
H
0

This can be used in any class:

DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();
Integer with = metrics.widthPixels;
Integer height = metrics.heightPixels;

Hope this help

Hibbitts answered 28/7, 2018 at 16:21 Comment(0)
K
0

Even simpler than accepted answer. You don't need context.

object ScreenUtils {

    fun getScreenWidth() = Resources.getSystem().displayMetrics.widthPixels

    fun getScreenHeight() = Resources.getSystem().displayMetrics.heightPixels

}
Karakorum answered 27/2, 2020 at 11:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.