他们(Google 开发人员)邀请您在 Jetpack Compose Layouts路径中尝试添加其他 Material Design 组件,例如 BottomNavigation
或BottomDrawer
到它们各自的Scaffold
slot,但没有给您解决方案。
BottomAppBar
在(ie )中确实有自己的插槽,但没有 - 并且似乎专门设计用于明确地与 BottomAppBar 一起使用(请参阅 BottomDrawer的 API 文档)。Scaffold
bottomBar
BottomDrawer
在 Jetpack Compose 路径的这一点上,我们已经介绍了状态提升、插槽、修饰符,并且已经被彻底解释过,我们将不时地尝试看看如何最好地堆叠和组织 Composables——它们几乎总是有一种自然可表达的方式,使它们在实际中发挥最佳作用。
让我进行设置,以便我们在同一页面上:
class MainActivity : ComponentActivity() {
@ExperimentalMaterialApi
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
LayoutsCodelabTheme {
// A surface container using the 'background' color from the theme
Surface(color = MaterialTheme.colors.background) {
LayoutsCodelab()
}
}
}
}
}
这是调用我们的主要/核心可组合的主要活动。这就像在代码实验室中一样,但@ExperimentalMaterialApi
注释除外。
接下来是我们的主要/核心可组合:
@ExperimentalMaterialApi
@Composable
fun LayoutsCodelab() {
val ( gesturesEnabled, toggleGesturesEnabled ) = remember { mutableStateOf( true ) }
val scope = rememberCoroutineScope()
val drawerState = rememberBottomDrawerState( BottomDrawerValue.Closed )
// BottomDrawer has to be the true core of our layout
BottomDrawer(
gesturesEnabled = gesturesEnabled,
drawerState = drawerState,
drawerContent = {
Button(
modifier = Modifier.align( Alignment.CenterHorizontally ).padding( top = 16.dp ),
onClick = { scope.launch { drawerState.close() } },
content = { Text( "Close Drawer" ) }
)
LazyColumn {
items( 25 ) {
ListItem(
text = { Text( "Item $it" ) },
icon = {
Icon(
Icons.Default.Favorite,
contentDescription = "Localized description"
)
}
)
}
}
},
// The API describes this member as "the content of the
// rest of the UI"
content = {
// So let's place the Scaffold here
Scaffold(
topBar = {
AppBarContent()
},
//drawerContent = { BottomBar() } // <-- Will implement a side drawer
bottomBar = {
BottomBarContent(
coroutineScope = scope,
drawerState = drawerState
)
},
) {
innerPadding ->
BodyContent( Modifier.padding( innerPadding ).fillMaxHeight() )
}
}
)
}
在这里,我们Scaffold
完全按照 compose 路径中的 codelab 所建议的那样利用了。请注意我的评论drawerContent
是侧抽屉的自动实现。这是直接使用[各自的] Composable(s)(材料设计的模态抽屉/工作表)绕过的一种相当不错的方法!但是,它不适用于我们的BottomDrawer
. 我认为 API 是实验性的BottomDrawer
,因为他们将Scaffold
在未来进行更改以添加对 Composables 的支持。
我的基础是使用 的难度BottomDrawer
,设计仅与 一起使用BottomAppBar
,与Scaffold
- 显式包含一个插槽用于BottomAppBar
.
为了支持BottomDrawer
,我们必须了解它是一个底层布局控制器,它封装了整个应用程序的 UI,防止与drawerContent
抽屉打开时以外的任何东西进行交互。这要求它包含Scaffold
,并且要求我们将必要的状态控制委托给BottomBarContent
包装我们的实现的可组合BottomAppBar
:
@ExperimentalMaterialApi
@Composable
fun BottomBarContent( modifier: Modifier = Modifier, coroutineScope: CoroutineScope, drawerState: BottomDrawerState ) {
BottomAppBar{
// Leading icons should typically have a high content alpha
CompositionLocalProvider( LocalContentAlpha provides ContentAlpha.high ) {
IconButton(
onClick = {
coroutineScope.launch { drawerState.open() }
}
) {
Icon( Icons.Filled.Menu, contentDescription = "Localized description" )
}
}
// The actions should be at the end of the BottomAppBar. They use the default medium
// content alpha provided by BottomAppBar
Spacer( Modifier.weight( 1f, true ) )
IconButton( onClick = { /* doSomething() */ } ) {
Icon( Icons.Filled.Favorite, contentDescription = "Localized description" )
}
IconButton( onClick = { /* doSomething() */ } ) {
Icon( Icons.Filled.Favorite, contentDescription = "Localized description" )
}
}
}
结果告诉我们:
- 顶部的TopAppBar,_
- 底部的BottomAppBar,_
- 单击BottomAppBar中的菜单图标将打开我们的BottomDrawer,在打开时适当地覆盖 BottomAppBar 和整个内容空间。
- BottomDrawer被正确隐藏,直到使用上面提到的按钮单击或手势来打开底部抽屉。
- BottomAppBar中的菜单图标会在中途打开抽屉。
- 手势通过快速短扫来中途打开底部抽屉,但只要你引导它。