Alexander Hoffmann
Alexander Hoffmann

Reputation: 6024

How to calculate WindowSizeClass in Jetpack Compose @Preview

I want to preview my top level Jetpack Compose screen and check if it correctly adapts to different screen sizes. I use the width of WindowSizeClass to decide how to render the screen. This is the currently suggested method in the Android dev guide.

How can I preview if my composable is working as intended on multiple devices without hard coding the value for WindowWidthSizeClass?

Ideally I would want to use calculateWindowSizeClass which requires an Activity as a parameter. But this doesn't work in a Preview unless I deploy it to a device.

My current preview looks like this:

@ExperimentalMaterial3WindowSizeClassApi
@Preview(
    name = "Smartphone, Nokia X20",
    group = "Smartphone",
    showSystemUi = true,
    device = "spec:width=1080px,height=2400px,dpi=400",

    )
@Preview(
    name = "Tablet, Nokia T20",
    group = "Tablet",
    showSystemUi = true,
    device = "spec:width=1200px,height=2000px,dpi=280"
)
@Composable
fun MasterDataScreenPreview() {
    // calculateWindowSizeClass does not work in Android Studio Preview.
    val windowWidthSize = calculateWindowSizeClass(LocalContext.current.getActivity()!!).widthSizeClass
    MyAppTheme {
        Surface {
            MainScreenContent(
                uiState = MainScreenUiState(),
                windowSize = windowWidthSize,
            )
        }
    }
}

fun Context.getActivity(): ComponentActivity? = when (this) {
    is ComponentActivity -> this
    is ContextWrapper -> baseContext.getActivity()
    else -> null
}

Alternatively I could split this single preview in two separate previews and pass WindowWidthSizeClass.Compact for the smartphone and WindowWidthSizeClass.Medium for the tablet preview.

But this kinda beats the purpose of defining specific preview screen sizes and checking if the layout adapts properly.

Upvotes: 4

Views: 3219

Answers (2)

Jason Capriotti
Jason Capriotti

Reputation: 2060

I looked at the answer from @Jan Bína and found out using the library requires API 34.

I'm still using API 33 so I cobbled together a solution based on the library's code and the code from calculateWindowSizeClass (in androidx.compose.material3.windowsizeclass). It seems to work for my purposes.

@OptIn(ExperimentalMaterial3WindowSizeClassApi::class)
@Composable
fun currentWindowAdaptiveInfo(): WindowSizeClass {
    val configuration = LocalConfiguration.current
    val size = DpSize(configuration.screenWidthDp.dp, configuration.screenHeightDp.dp)
    return WindowSizeClass.calculateFromSize(size)
}

Upvotes: 4

Jan Bína
Jan Bína

Reputation: 7278

Google just released new material3-adaptive library. It contains currentWindowAdaptiveInfo() function that returns WindowAdaptiveInfo which has a WindowSizeClass and it doesn't depend on activity. You can either use it directly, or at least as an inspiration how to do that.

@Preview @Composable fun ScreenPreview() {
    val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass
}

Upvotes: 5

Related Questions