Jetpack Compose组件-Scaffold

前言

在 Jetpack Compose 里,Scaffold 是一个非常关键的组件,它为构建应用界面提供了基础的布局结构,极大地简化了常见界面的搭建过程。

用途概述

Scaffold 组件可用于创建具备标准 Android 界面布局的应用,都能借助 Scaffold 轻松实现。

比如:

  • 顶部导航栏。
  • 底部导航栏。
  • 抽屉式导航菜单。
  • 浮动操作按钮。

基本

1
2
3
4
5
6
7
8
9
10
11
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
Box(
modifier = Modifier
.padding(innerPadding)
.background(Color.Green)
.fillMaxWidth()
.fillMaxHeight()
) {

}
}

默认内部是content,提供innerPadding能够把顶部状态栏的空间排除掉。

innerPadding 值规则

1
2
3
4
5
6
7
8
9
10
Scaffold(
modifier = Modifier.statusBarsPadding(),
topBar = {
MyTopBar()
},
)
{
innerPadding ->

}

innerPadding的值是动态计算的。

比如上面的示例,我们已经把状态栏的位置padding掉了,并且自定义的topBar,高度为44dp,底部使用的全面屏手势。

实际的值是

1
2
3
4
5
6
PaddingValues(
start = 0.dp,
top = 44.dp,
end = 0.dp,
bottom = 12.dp
)

如果

  • 设备有状态栏(比如 24dp 高),

  • TopAppBar 默认高度是 56dp,

  • 底部导航栏(BottomAppBar)可能是 56dp 或者是12dp(全面屏手势)。

那么innerPadding可能大致为:

1
2
3
4
5
6
PaddingValues(
start = 0.dp,
top = 24.dp + 56.dp, // 状态栏 + TopAppBar
end = 0.dp,
bottom = 12.dp // BottomAppBar
)

实际值取决于设备、是否显示导航栏、是否使用 edge-to-edge 等设置。

全面屏背景

Scaffold 默认是白色的背景,直接设置组件的背景是无效的,它的背景会使用内容中顶层容器(如 BoxSurface)的背景。

topBar会占到状态栏上,我们可以topBar上设置statusBarsPadding(),也可以直接对Scaffold的modifier设置statusBarsPadding(),但是这样状态栏会是白色。

所以建议还是在topBar上设置statusBarsPadding()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Scaffold(
modifier = Modifier,
topBar = {
Box(Modifier.statusBarsPadding()) {
ZPageTopBar(title = "EchoTalk", backAction = {})
}
},
content = {
innerPadding ->
Row(
modifier = Modifier
.fillMaxSize()
.paint(
painterResource(id = R.drawable.bg_en),
contentScale = ContentScale.FillBounds
)
.padding(innerPadding)
) {

}
}
)

顶部栏

Scaffold 能够在界面顶部添加一个导航栏,这个导航栏可用于展示应用标题、操作按钮等信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color

@Composable
fun ScaffoldWithTopAppBar() {
Scaffold(
topBar = {
TopAppBar(
title = { Text(text = "My App") },
backgroundColor = Color.Blue,
contentColor = Color.White
)
},
content = { innerPadding ->
// 主内容区域
Text(text = "This is the main content", modifier = androidx.compose.ui.Modifier.padding(innerPadding))
}
)
}

在这个示例中,topBar 参数设置了一个 TopAppBar,其标题为 “My App”,背景颜色是蓝色,文字颜色为白色。

底部栏

Scaffold 也支持在界面底部添加导航栏,底部导航栏常用于应用的主要导航操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Composable
fun ScaffoldWithBottomAppBar() {
Scaffold(
bottomBar = {
BottomAppBar(
backgroundColor = Color.Blue,
contentColor = Color.White
) {
Text(text = "Bottom Navigation")
}
},
content = { innerPadding ->
Text(text = "This is the main content", modifier = androidx.compose.ui.Modifier.padding(innerPadding))
}
)
}

此例中,bottomBar 参数添加了一个 BottomAppBar,并在其中显示了 “Bottom Navigation” 文本。

抽屉式导航菜单

Scaffold 允许添加抽屉式导航菜单,通过侧滑操作可以打开或关闭该菜单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Menu
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton

@Composable
fun ScaffoldWithDrawer() {
val scaffoldState = rememberScaffoldState()
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopAppBar(
title = { Text(text = "My App") },
navigationIcon = {
IconButton(onClick = {
// 点击菜单图标时打开抽屉
scaffoldState.drawerState.open()
}) {
Icon(Icons.Default.Menu, contentDescription = "Menu")
}
}
)
},
drawerContent = {
Text(text = "Drawer Content")
},
content = { innerPadding ->
Text(text = "This is the main content", modifier = androidx.compose.ui.Modifier.padding(innerPadding))
}
)
}

在这个示例中,drawerContent 参数定义了抽屉式导航菜单的内容,通过点击顶部栏的菜单图标可以打开抽屉。

浮动操作按钮

Scaffold 还能添加浮动操作按钮,该按钮通常用于执行应用的主要操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
@Composable
fun ScaffoldWithFab() {
Scaffold(
floatingActionButton = {
FloatingActionButton(onClick = { /* 点击按钮时执行的操作 */ }) {
Text(text = "+")
}
},
content = { innerPadding ->
Text(text = "This is the main content", modifier = androidx.compose.ui.Modifier.padding(innerPadding))
}
)
}

这里,floatingActionButton 参数添加了一个 FloatingActionButton,按钮上显示了 “+” 号。

综上所述,Scaffold 组件为开发者提供了一种便捷的方式来构建具有常见 UI 元素的应用界面,通过组合不同的参数,可以快速实现多样化的界面布局。