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

Jetpack Compose 中打开抽屉时如何滑动平移 Scaffold 内容

Jetpack Compose 实现侧边抽屉打开时平移Scaffold内容的方案

实现思路

原生Scaffold默认的抽屉效果是覆盖在主内容上方,要实现抽屉展开时推挤主内容平移的效果,不需要自定义复杂的抽屉组件,直接复用官方抽屉状态监听逻辑即可:

  • 用官方提供的DrawerState监听抽屉的展开进度,无需自定义状态变量
  • 根据抽屉的展开进度计算主内容的水平偏移量,最大偏移量可自定义为抽屉的宽度
  • 给Scaffold添加偏移修饰符,让主内容的偏移跟随抽屉进度实时变化,实现平滑联动效果

核心实现代码

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun PushContentDrawerDemo() {
    // 初始化抽屉状态和协程作用域
    val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
    val scope = rememberCoroutineScope()
    // 自定义抽屉宽度,可根据需求调整
    val drawerWidth = 300.dp
    // 计算主内容最大偏移像素值
    val maxContentOffset = with(LocalDensity.current) { drawerWidth.toPx() }

    ModalNavigationDrawer(
        drawerState = drawerState,
        drawerContent = {
            // 抽屉内容布局
            ModalDrawerSheet(modifier = Modifier.width(drawerWidth)) {
                Text("菜单项1", modifier = Modifier.padding(vertical = 16.dp, horizontal = 24.dp))
                Text("菜单项2", modifier = Modifier.padding(vertical = 16.dp, horizontal = 24.dp))
                Text("菜单项3", modifier = Modifier.padding(vertical = 16.dp, horizontal = 24.dp))
            }
        }
    ) {
        Scaffold(
            topBar = {
                TopAppBar(
                    title = { Text("主页") },
                    navigationIcon = {
                        IconButton(onClick = {
                            scope.launch {
                                if (drawerState.isOpen) drawerState.close() else drawerState.open()
                            }
                        }) {
                            Icon(Icons.Default.Menu, contentDescription = "打开抽屉")
                        }
                    }
                )
            },
            // 核心逻辑:绑定主内容偏移和抽屉展开进度
            modifier = Modifier.graphicsLayer {
                translationX = drawerState.offset.value.coerceAtLeast(0f)
            }
        ) { innerPadding ->
            // 主内容布局
            Box(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(innerPadding)
            ) {
                Text("主页面内容", modifier = Modifier.align(Alignment.Center))
            }
        }
    }
}

注意事项

  • 如果你使用的是Material2版本的Compose组件,将ModalNavigationDrawer替换为Drawer组件即可,状态监听逻辑完全一致
  • 使用graphicsLayer设置偏移比使用offset修饰符性能更好,不需要反复做px和dp的单位转换,且默认开启硬件加速
  • 如果需要额外增加动效,可以在graphicsLayer中添加缩放、圆角属性,示例:scaleX = 1f - (drawerState.offset.value / maxContentOffset * 0.1f),即可实现内容右移同时轻微缩小的效果
  • 部分低版本Compose中drawerState.offset不可用,可以用(if (drawerState.isOpen) 1f else 0f)配合animateFloatAsState实现过渡动画,效果一致

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.11 11:15:00