You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Compose Multiplatform中不使用expect/actual获取屏幕尺寸?

在Compose Multiplatform中不使用expect/actual获取尺寸的方案实现

核心思路

通过Layout作为根Composable,利用其传入的constraints获取当前可用空间尺寸,再通过CompositionLocal将尺寸传递到整个Compose树中。该方案不依赖平台实现,能拿到当前Composable的实际可用尺寸(若根Layout铺满屏幕,则等价于屏幕可用区域尺寸)。

完整实现步骤

  1. 定义尺寸传递的CompositionLocal
    首先创建一个CompositionLocal来承载尺寸数据,方便在Compose树中全局访问:
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember

// 封装尺寸数据的数据类
data class WindowSize(val width: Int, val height: Int)

// 创建CompositionLocal,默认值为(0,0)
val LocalWindowSize = compositionLocalOf { WindowSize(0, 0) }
  1. 实现根Layout组件
    编写一个自定义Layout作为App的根组件,在其中获取约束尺寸并更新CompositionLocal的值:
import androidx.compose.foundation.layout.Layout
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.layout.Measurable
import androidx.compose.ui.layout.MeasureScope
import androidx.compose.ui.unit.Constraints

@Composable
fun WindowSizeLayout(content: @Composable () -> Unit) {
    // 保存当前尺寸,支持状态更新(比如屏幕旋转、窗口调整)
    var windowSize by remember { mutableStateOf(WindowSize(0, 0)) }

    Layout(
        content = {
            // 通过CompositionLocalProvider将最新尺寸传递给子组件
            CompositionLocalProvider(LocalWindowSize provides windowSize) {
                content()
            }
        }
    ) { measurables, constraints ->
        // 获取当前Layout的最大可用尺寸
        val newSize = WindowSize(constraints.maxWidth, constraints.maxHeight)
        // 尺寸变化时更新状态,触发重组
        if (newSize != windowSize) {
            windowSize = newSize
        }

        // 测量子组件,让其铺满整个可用空间
        val placeables = measurables.map { it.measure(constraints) }

        // 布局子组件,铺满整个Layout区域
        layout(constraints.maxWidth, constraints.maxHeight) {
            placeables.forEach { it.place(0, 0) }
        }
    }
}
  1. 在子组件中使用尺寸
    在任意子Composable中,通过LocalWindowSize.current即可获取当前可用尺寸:
import androidx.compose.material.Text
import androidx.compose.ui.unit.dp

@Composable
fun DisplayCurrentSize() {
    val size = LocalWindowSize.current
    Text(
        text = "可用宽度:${size.width.dp}\n可用高度:${size.height.dp}"
    )
}
  1. 在App根组件中应用
    将WindowSizeLayout作为App的根容器,包裹所有内容:
@Composable
fun MyApp() {
    WindowSizeLayout {
        // 这里放置你的整个App内容
        DisplayCurrentSize()
        // 其他自定义Composable...
    }
}

注意事项

  • 该方案获取的是当前Layout的可用空间尺寸,若根Layout未铺满屏幕(比如存在系统状态栏、导航栏),则尺寸会扣除这些区域的空间。如果需要设备物理屏幕的原始尺寸,仍需使用expect/actual方案。
  • 当屏幕旋转、窗口大小调整时,尺寸会自动更新,无需额外监听逻辑。

内容的提问来源于stack exchange,提问作者Roy Solberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 17:15:32