
In this article, we’ll learn how to get the device screen size (height and width) in Jetpack Compose.
Prerequisites:
For this article, create an empty Jetpack Compose project and open MainActivity. Create a composable called ScreenSize() and call it from the onCreate().
// we need the following packages
import android.content.res.Configuration
import android.graphics.Point
import android.hardware.display.DisplayManager
import android.os.Build
import android.os.Bundle
import android.view.Display
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.core.view.WindowCompat
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme(darkTheme = false) {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 12.dp),
verticalArrangement = Arrangement.Center
) {
ScreenSize()
}
}
}
}
}
}
@Composable
fun ScreenSize() {
}
We’ll write our code in ScreenSize().
There are two ways to get the screen height and width in Jetpack Compose:
1. Using LocalConfiguration:
LocalConfiguration provides screenWidthDp and screenHeightDp values.
@Composable
fun ScreenSize() {
val configuration = LocalConfiguration.current
val widthInDp = configuration.screenWidthDp.dp
val heightInDp = configuration.screenHeightDp.dp
Text(text = "widthInDp = $widthInDp, heightInDp = $heightInDp")
}
Output:

If you want to convert them to pixels, use the LocalDensity API.
@Composable
fun ScreenSize() {
val configuration = LocalConfiguration.current
val density = LocalDensity.current
val widthInDp = configuration.screenWidthDp.dp
val heightInDp = configuration.screenHeightDp.dp
val widthInPx = with(density) { widthInDp.roundToPx() }
val heightInPx = with(density) { heightInDp.roundToPx() }
Text(text = "widthInPx = $widthInPx, heightInPx = $heightInPx")
}
Output:

The above code doesn’t consider the status bar and navigation bar heights (even if the app is in full-screen mode). So, we need to calculate the values to get the actual height of the device.
First, add the following line before the setContent block in the onCreate() method.
WindowCompat.setDecorFitsSystemWindows(window, false)
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// add here
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
YourProjectNameTheme(darkTheme = false) {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 12.dp),
verticalArrangement = Arrangement.Center
) {
ScreenSize()
}
}
}
}
}
}
Next, we can get the system bars height using the WindowInsets API.
@Composable
fun ScreenSize() {
val configuration = LocalConfiguration.current
val density = LocalDensity.current
val heightInDp = configuration.screenHeightDp.dp
val navigationBarHeightDp = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
val statusBarHeightDp = WindowInsets.systemBars.asPaddingValues().calculateTopPadding()
Text(text = "navigationBarHeightDp = $navigationBarHeightDp, statusBarHeightDp = $statusBarHeightDp")
val totalHeightInDp = heightInDp + navigationBarHeightDp + statusBarHeightDp
val totalHeightInPx = with(density) { totalHeightInDp.roundToPx() }
Spacer(modifier = Modifier.height(height = 8.dp)) // padding
Text(text = "totalHeightInPx = $totalHeightInPx")
}
Output:

Here is the complete code:
@Composable
fun ScreenSize() {
val configuration = LocalConfiguration.current
val density = LocalDensity.current
val widthInDp = configuration.screenWidthDp.dp
val heightInDp = configuration.screenHeightDp.dp
val widthInPx = with(density) { widthInDp.roundToPx() }
val heightInPx = with(density) { heightInDp.roundToPx() }
Text(text = "widthInPx = $widthInPx, heightInPx = $heightInPx")
val navigationBarHeightDp = WindowInsets.systemBars.asPaddingValues().calculateBottomPadding()
val statusBarHeightDp = WindowInsets.systemBars.asPaddingValues().calculateTopPadding()
Spacer(modifier = Modifier.height(height = 8.dp)) // padding
Text(text = "navigationBarHeightDp = $navigationBarHeightDp, statusBarHeightDp = $statusBarHeightDp")
val totalHeightInDp = heightInDp + navigationBarHeightDp + statusBarHeightDp
val totalHeightInPx = with(density) { totalHeightInDp.roundToPx() }
Spacer(modifier = Modifier.height(height = 8.dp)) // padding
Text(text = "totalHeightInPx = $totalHeightInPx")
}
Output:

When the device is rotated, the height and width values are changed accordingly. You can find the device orientation using the LocalConfiguration API.
val configuration = LocalConfiguration.current
if (configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
// landscape mode
} else if (configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
// portrait mode
}
There are 2 problems with LocalConfiguration API:
1. From the previous output, the screen size is 1078 X 2338. But the actual size is 1080 X 2440. I got this problem with some emulators. I am not sure why this is happening. However, I got the correct output on my Samsung mobile.
2. In multi-window mode, LocalConfiguration returns the app window screen size, not the actual device size. For example, apps are displayed side by side in a split-screen mode in landscape orientation.
2. Using WindowManager:
This method works both in XML and Jetpack Compose. WindowManager and DisplayManager provide methods to calculate the device height and width.
Here is the complete code:
import android.graphics.Point
import android.hardware.display.DisplayManager
import android.os.Build
import android.os.Bundle
import android.view.Display
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val windowManager = getSystemService(WINDOW_SERVICE) as WindowManager
val displayManager = getSystemService(DISPLAY_SERVICE) as DisplayManager
setContent {
YourProjectNameTheme(darkTheme = false) {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(horizontal = 12.dp),
verticalArrangement = Arrangement.Center
) {
ScreenSize(windowManager, displayManager)
}
}
}
}
}
}
@Composable
fun ScreenSize(
windowManager: WindowManager,
displayManager: DisplayManager
) {
var deviceHeight = 0
var deviceWidth = 0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val wMetrics = windowManager.currentWindowMetrics
val bounds = wMetrics.bounds
deviceHeight = bounds.height()
deviceWidth = bounds.width()
} else {
val displayInfo =
displayManager.getDisplay(
Display.DEFAULT_DISPLAY
)
val realSize = Point()
Display::class.java.getMethod("getRealSize", Point::class.java)
.invoke(displayInfo, realSize)
displayInfo.getRealSize(realSize)
deviceWidth = realSize.x
deviceHeight = realSize.y
}
Text(text = "deviceWidth = $deviceWidth, deviceHeight = $deviceHeight")
}
Output:

This is all about getting the screen size in Jetpack Compose. I hope you have learned something new. If you have any doubts, comment below.
Related Articles:
- LazyColumn in Jetpack Compose
- SVG to XML Conversion in Android Studio
- 3 Ways to Disable Ripple Effect in Jetpack Compose
References: