Jetpack Compose 中的 Scaffold — 它是什么、属性及工作原理

作者: IT Sectr 发布日期: 2026-06-29 阅读时间: 11 分钟

Scaffold — 是 Jetpack Compose 中的一个 composable 函数,实现了基于 Material Design 规范的基本屏幕结构。Scaffold 为 TopAppBar、BottomBar、FloatingActionButton、Drawer 和 Snackbar 提供插槽。根据 Google Android Documentation, 2025,Scaffold 是 Compose 应用程序中大多数屏幕的必要元素,因为它管理 Material Design 系统组件的间距。

要点

  • Scaffold — Material Design 屏幕框架,为 TopAppBar、BottomBar、FAB、Drawer 和 Snackbar 提供插槽并具有正确的间距。
  • ScaffoldState 管理 Drawer 和 Snackbar 的状态,确保侧边菜单的打开和关闭以及通知的显示。
  • topBarbottomBarfloatingActionButton — Scaffold 的插槽,用于集成标准 Material Design 组件。
  • drawerGesturesEnabled 管理侧边菜单的手势打开,而 snackbarHost 管理 Snackbar 的自定义显示。
  • Scaffold 通过 innerPadding 自动管理状态栏和导航面板的间距。

Jetpack Compose 中的 Scaffold 是什么

Scaffold — 是一个 composable 函数,实现了基于 Material Design 规范的屏幕框架。Scaffold 不是常规意义上的容器——它是一个布局管理器,协调多个标准 Material 组件在屏幕上的位置。

Scaffold 管理 TopAppBar、BottomBar 和 FloatingActionButton 的间距,以及系统元素——状态栏和导航面板。这保证内容不会覆盖系统元素,并符合 Material Design 指南。

根据 Material Design Guidelines, 2025,Scaffold 应该是每个应用程序屏幕的根元素。它取代了 View 系统中过时的 CoordinatorLayout,并提供了更简单、更声明式的 API 来构建屏幕布局。

Scaffold 的基本签名

Scaffold 接受 modifier、scaffoldState、topBar、bottomBar、floatingActionButton、drawerContent、snackbarHost 和 content 参数。Content 参数接收 PaddingValues——主要内容必须考虑的间距。

kotlin
@Composable
fun BasicScaffold() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("首页") }
            )
        },
        floatingActionButton = {
            FloatingActionButton(onClick = {}) {
                Icon(Icons.Default.Add, contentDescription = "Add")
            }
        }
    ) { innerPadding ->
        Column(
            modifier = Modifier.padding(innerPadding)
        ) {
            Text("主要内容")
        }
    }
}

Scaffold 插槽:topBar、bottomBar 和 floatingActionButton

topBar — 用于放置应用程序顶部面板的插槽,通常是 TopAppBar 或 LargeTopAppBar。Scaffold 自动在 innerPadding 中为内容添加间距,以避免内容覆盖 topBar。TopAppBar 可以包含标题、导航图标和操作。

bottomBar — 用于底部导航面板的插槽。支持 BottomNavigation、BottomAppBar 或 NavigationBar。Scaffold 在计算内容的 innerPadding 时会考虑 bottomBar 的高度。根据 Material Design Guidelines, 2025,bottomBar 应用于具有 3–5 个导航点的屏幕。

floatingActionButton — 用于浮动操作按钮的插槽。Scaffold 根据 Material Design 规范自动定位 FAB——在右下角并具有正确的间距。floatingActionButtonPosition 允许将 FAB 移动到屏幕底部边缘的中央。

使用所有插槽的示例

在这个示例中,Scaffold 使用了所有主要插槽:带标题的 TopAppBar、带三个导航元素的 BottomBar 和用于主要操作的 FloatingActionButton。

kotlin
@Composable
fun FullScaffold() {
    Scaffold(
        topBar = {
            TopAppBar(
                title = { Text("应用") },
                navigationIcon = {
                    IconButton(onClick = {}) {
                        Icon(Icons.Default.Menu, "Menu")
                    }
                }
            )
        },
        bottomBar = {
            NavigationBar {
                NavigationBarItem(
                    icon = { Icon(Icons.Default.Home, "首页") },
                    label = { Text("Home") },
                    selected = true,
                    onClick = {}
                )
                NavigationBarItem(
                    icon = { Icon(Icons.Default.Search, "搜索") },
                    label = { Text("Search") },
                    selected = false,
                    onClick = {}
                )
            }
        },
        floatingActionButton = {
            FloatingActionButton(onClick = {}) {
                Icon(Icons.Default.Add, "Add")
            }
        }
    ) { innerPadding ->
        Box(modifier = Modifier.padding(innerPadding)) {
            Text("屏幕内容")
        }
    }
}

ScaffoldState:管理 Drawer 和 Snackbar

ScaffoldState — Scaffold 的状态对象,组合了 DrawerState 和 SnackbarHostState。DrawerState 管理侧边菜单的打开和关闭,而 SnackbarHostState 管理 Snackbar 的显示和隐藏。状态通过 rememberScaffoldState() 创建并传递给 scaffoldState 参数。

DrawerState 提供 open 和 close 方法用于编程控制 Drawer。Drawer 的状态可以是打开、关闭或部分打开。drawerGesturesEnabled 允许禁用通过滑动打开 Drawer 的手势,仅保留通过按钮的编程打开。

SnackbarHostState 管理 Snackbar——屏幕底部的临时通知。showSnackbar 方法显示带有消息和可选操作的 Snackbar。根据 Material Design Guidelines, 2025,Snackbar 应用于短消息,无关键重要信息。

kotlin
@Composable
fun ScaffoldWithDrawer() {
    val scaffoldState = rememberScaffoldState()
    val scope = rememberCoroutineScope()

    Scaffold(
        scaffoldState = scaffoldState,
        topBar = {
            TopAppBar(
                title = { Text("菜单") },
                navigationIcon = {
                    IconButton(onClick = {
                        scope.launch {
                            scaffoldState.drawerState.open()
                        }
                    }) {
                        Icon(Icons.Default.Menu, "Menu")
                    }
                }
            )
        },
        drawerContent = {
            Column(modifier = Modifier.padding(16.dp)) {
                Text("项目 1")
                Text("项目 2")
            }
        }
    ) { innerPadding ->
        Box(modifier = Modifier.padding(innerPadding)) {
            Text("内容")
        }
    }
}

使用 Scaffold 构建屏幕的示例

一个完整的屏幕示例使用 Scaffold 包括 TopAppBar、BottomNavigation、FloatingActionButton 和 Snackbar,用于在按下 FAB 时显示通知。ScaffoldState 传递给所有组件以协调状态。

kotlin
@Composable
fun MainScreen() {
    val state = rememberScaffoldState()
    val scope = rememberCoroutineScope()

    Scaffold(
        scaffoldState = state,
        topBar = {
            TopAppBar(
                title = { Text("IT Sectr") },
                actions = {
                    IconButton(onClick = {}) {
                        Icon(Icons.Default.Notifications, "Notifications")
                    }
                }
            )
        },
        bottomBar = {
            NavigationBar {
                NavigationBarItem(icon = { Icon(Icons.Default.Home, "首页") },
                    label = { Text("Home") }, selected = true, onClick = {})
                NavigationBarItem(icon = { Icon(Icons.Default.Settings, "设置") },
                    label = { Text("Settings") }, selected = false, onClick = {})
            }
        },
        floatingActionButton = {
            FloatingActionButton(onClick = {
                scope.launch {
                    state.snackbarHostState.showSnackbar("完成")
                }
            }) {
                Icon(Icons.Default.Add, "Add")
            }
        }
    ) { padding ->
        Box(
            modifier = Modifier.padding(padding).fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            Text("欢迎")
        }
    }
}

InnerPadding 和使用 Scaffold 的自适应布局

innerPadding — 是 Scaffold 传递给 content 块的 PaddingValues。它们包含内容不覆盖 statusBar、navigationBar、topBar 和 bottomBar 所需的间距。使用 innerPadding 是在不同设备上正确显示的必要条件。

Scaffold 根据系统间距和安装的插槽高度自动计算 innerPadding。在具有摄像头岛嵦或屏幕切口的设备上,Scaffold 会调整状态栏的间距。在具有物理按钮的老式设备上,底部间距可能为零。

根据 Android Developers, 2024,innerPadding 应通过 Modifier.padding(innerPadding) 应用于内容的根容器。如果内容使用可滚动容器,则通过 Modifier.consumeWindowInsets 应用 innerPadding,以确保键盘和系统手势的正确操作。

  • 通过 Modifier.padding(innerPadding) 将 innerPadding 应用于内容的根容器
  • 对于可滚动容器,使用 Modifier.consumeWindowInsets(innerPadding)
  • 不要为状态栏添加额外间距——Scaffold 自动处理
  • 如果没有 topBar 或 bottomBar,innerPadding 中的相应间距将为零

常见问题

Scaffold 与普通的 Column 或 Box 有什么区别?

Scaffold 不是容器,而是布局管理器,管理 TopAppBar、BottomBar、FAB、Drawer 和 Snackbar 的插槽,并自动处理系统组件的间距。Column 和 Box 仅根据位置元素,不考虑 Material Design。

是否必须在每个屏幕上使用 Scaffold?

Scaffold 建议用于使用 Material Design 组件的屏幕。在没有 TopAppBar、BottomBar 或 FAB 的简单屏幕上,Scaffold 不是必须的,但它通过 innerPadding 提供正确的系统间距,这在没有插槽时也很有用。

如何通过 Scaffold 显示 Snackbar?

ScaffoldState 传递给 Scaffold 的 scaffoldState 参数,然后在 coroutine 内调用 state.snackbarHostState.showSnackbar(“消息”)。Scaffold 将自动在屏幕底部显示 Snackbar。

可以不使用 scaffoldState 而使用 Scaffold 吗?

可以,如果没有传递 scaffoldState,Scaffold 会默认创建内部状态。但要编程控制 Drawer 和 Snackbar,您需要通过 rememberScaffoldState() 创建并传递 ScaffoldState。

如何改变 Scaffold 中 FloatingActionButton 的位置?

使用 Scaffold 的 floatingActionButtonPosition 参数。默认情况下,FAB 位于右下角 (FabPosition.End)。设置 FabPosition.Center 可将 FAB 放置在屏幕底部边缘的中央。

总结

  • Scaffold — Material Design 屏幕框架,管理 TopAppBar、BottomBar、FAB、Drawer 和 Snackbar 的插槽并自动处理系统间距。
  • topBarbottomBarfloatingActionButton — Scaffold 插槽,用于集成标准组件并具有正确定位。
  • ScaffoldState 组合 DrawerState 和 SnackbarHostState,通过 coroutine 提供侧边菜单和通知的编程控制。
  • innerPadding — content 块的必要参数,包含系统元素和安装的 Scaffold 插槽的间距。
  • drawerGesturesEnabledfloatingActionButtonPosition — 用于精调 Scaffold 行为的额外参数。
  • Scaffold 自动处理不同屏幕配置的设备上状态栏和导航面板的间距。
  • 对于没有 Material 组件的简单屏幕,Scaffold 不是必须的,但建议作为根元素以确保系统间距的正确操作。

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读