如何在@Preview可组合函数中使用calculateWindowSizeClass(activity = this)
如何在@Preview可组合函数中使用calculateWindowSizeClass(activity = this)
嘿,我懂你碰到的难题了——在@Preview可组合函数里想用calculateWindowSizeClass确实有点棘手,毕竟Preview环境里根本没有真实的Activity实例,直接传this肯定会报错对吧?别慌,我给你几个实用的解决办法,帮你搞定预览问题:
方法1:手动创建WindowSizeClass模拟不同设备尺寸
既然Preview里拿不到真实的Activity,那我们就直接手动构造WindowSizeClass实例,模拟不同设备的尺寸就行。这样你还能精准控制要预览的设备类型,比如手机、平板或者大屏设备。
示例代码:
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @Preview(showBackground = true, showSystemUi = true, backgroundColor = 0xffffff) @Composable private fun BottomNavigationBarPreview() { // 模拟普通手机的紧凑宽度尺寸类 val windowSizeClass = WindowSizeClass.calculateFromSize( size = DpSize(width = 360.dp, height = 640.dp) ) // 把构造好的windowSizeClass传给你的BottomNavigationBar BottomNavigationBar(windowSizeClass = windowSizeClass) }
你可以随便调整width和height的数值,比如想预览平板效果就改成width = 1200.dp,非常灵活。
方法2:用PreviewParameter一次性预览多种尺寸
如果你想同时预览多种尺寸下的UI效果,不用写多个Preview函数,用PreviewParameter就能搞定。先写一个参数提供者,然后在Preview函数里接收即可:
首先定义一个PreviewParameterProvider:
class WindowSizeClassProvider : PreviewParameterProvider<WindowSizeClass> { @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) override val values = sequenceOf( // 紧凑宽度(手机) WindowSizeClass.calculateFromSize(DpSize(360.dp, 640.dp)), // 中等宽度(折叠屏/小平板) WindowSizeClass.calculateFromSize(DpSize(800.dp, 1280.dp)), // 扩展宽度(大屏平板/桌面) WindowSizeClass.calculateFromSize(DpSize(1200.dp, 1920.dp)) ) }
然后修改你的Preview函数:
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @Preview(showBackground = true, showSystemUi = true, backgroundColor = 0xffffff) @Composable private fun BottomNavigationBarPreview( @PreviewParameter(WindowSizeClassProvider::class) windowSizeClass: WindowSizeClass ) { BottomNavigationBar(windowSizeClass = windowSizeClass) }
这样Android Studio会自动生成三个预览窗口,分别对应三种不同的尺寸类效果,一次性看全所有场景。
方法3:封装兼容Preview的通用获取逻辑
如果你的Composable既要在真实运行环境使用,又要支持Preview,那可以封装一个通用的函数,自动判断当前环境并返回对应的WindowSizeClass:
@OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @Composable fun rememberWindowSizeClass(): WindowSizeClass { val context = LocalContext.current // LocalInspectionMode.current可以判断是否处于Preview环境 val isPreview = LocalInspectionMode.current return if (isPreview) { // Preview环境下返回默认的紧凑尺寸类,你也可以改成其他默认值 WindowSizeClass.calculateFromSize(DpSize(360.dp, 640.dp)) } else { // 真实环境下从Activity获取 calculateWindowSizeClass(activity = context as Activity) } }
之后不管是在真实的Composable里还是Preview里,都直接用这个函数就行:
@Composable fun BottomNavigationBar() { val windowSizeClass = rememberWindowSizeClass() // 这里写你的UI逻辑,根据windowSizeClass调整布局 } @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) @Preview(showBackground = true, showSystemUi = true, backgroundColor = 0xffffff) @Composable private fun BottomNavigationBarPreview() { BottomNavigationBar() }
这样就不用在Preview里单独处理,代码复用性也更高。
备注:内容来源于stack exchange,提问作者Ali Mohammadzadeh




