Jetpack Compose: Technique for Previewing Composable with Different Window Sizes
While studying responsive design with Jetpack Compose, I came across a new feature recommended by Google to assist in designing, developing, and testing adaptable layouts: Window Size Classes. This feature, detailed in the Android Documentation, helps organize layout elements across different screen sizes for a more consistent and accessible UI. Here’s how Android describes it:
Window size classes categorize the display area available to your app as compact, medium, or expanded. Available width and height are classified separately, so at any point in time, your app has two window size classes — one for width, one for height. Available width is usually more important than available height due to the ubiquity of vertical scrolling, so the width window size class is likely more relevant to your app’s UI.
Explaining the problem
When trying to preview composables with Window Size Classes, I faced an issue: every preview was treated as a compact screen, regardless of its width or height setting. Here’s an example:
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.PreviewScreenSizes
import androidx.window.core.layout.WindowHeightSizeClass
import androidx.window.core.layout.WindowSizeClass
@Composable
fun BackgroundExample(windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass) {
val backgroundColor =
when (windowSizeClass.windowHeightSizeClass) {
WindowHeightSizeClass.COMPACT -> Color.Red
WindowHeightSizeClass.MEDIUM -> Color.Green
else -> Color.Blue
}
Box(modifier = Modifier
.fillMaxSize()
.background(backgroundColor)
)
}
@Composable
@PreviewScreenSizes
fun PreviewExample() {
BackgroundExample()
}
Despite @PreviewScreenSizes
specify different screen sizes — Desktop, Phone, Landscape Phone, Tablet, and Foldable — the Window Size Classes still registered everything as compact. This bug means you can’t test accurately across screen types.
To address this issue, I found out a workaround. However, before implementing it, be sure to test without this solution, as Android may have resolved this bug in newer versions. If the issue persists, here’s the fix.
Exploring Solution
@Composable
fun BackgroundExample(windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass) {
...
}
@Composable
@PreviewScreenSizes
fun PreviewExample() {
val configuration = LocalConfiguration.current
val windowSizeClass = WindowSizeClass.compute(
dpHeight = configuration.screenHeightDp.toFloat(),
dpWidth = configuration.screenWidthDp.toFloat(),
)
BackgroundExample(windowSizeClass)
}
This approach uses LocalConfiguration
to fetch the screen's width and height, which are then used to compute the WindowSizeClass
. By directly passing these parameters, you can test how your composables behave across various screen types and improve responsiveness.
Leave a comment, give a like and connect with me on LinkedIn.