使用 Jetpack Compose 和 Material Design 时,是否可以在每个屏幕上使用新的
NavigationBar
(又名BottomNavigationBar
)?或者这会中断例如触摸动画作为新的NavigationBar
在切换屏幕时被实例化?
我的想法是,这真的可以很容易地在某些屏幕上隐藏或显示
NavigationBar
,而不是在其他屏幕上(而不是与层次结构中更高的Scaffold
进行通信)
BottomNavigation
composable 没有什么特别之处,您可以在下面的源代码中看到它
@Composable
fun BottomNavigation(
modifier: Modifier = Modifier,
backgroundColor: Color = MaterialTheme.colors.primarySurface,
contentColor: Color = contentColorFor(backgroundColor),
elevation: Dp = BottomNavigationDefaults.Elevation,
content: @Composable RowScope.() -> Unit
) {
Surface(
color = backgroundColor,
contentColor = contentColor,
elevation = elevation,
modifier = modifier
) {
Row(
Modifier
.fillMaxWidth()
.height(BottomNavigationHeight)
.selectableGroup(),
horizontalArrangement = Arrangement.SpaceBetween,
content = content
)
}
}
在每个屏幕上调用
BottomNavigation
类似于在任何屏幕上使用另一个可组合项。此外,BottomNavigationItem
只是一个 Box
或两个 Box
es 当标签和图标都存在时动画 alpha 和标签偏移的进度。
@Composable
fun RowScope.BottomNavigationItem(
selected: Boolean,
onClick: () -> Unit,
icon: @Composable () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
label: @Composable (() -> Unit)? = null,
alwaysShowLabel: Boolean = true,
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
selectedContentColor: Color = LocalContentColor.current,
unselectedContentColor: Color = selectedContentColor.copy(alpha = ContentAlpha.medium)
) {
val styledLabel: @Composable (() -> Unit)? = label?.let {
@Composable {
val style = MaterialTheme.typography.caption.copy(textAlign = TextAlign.Center)
ProvideTextStyle(style, content = label)
}
}
// The color of the Ripple should always the selected color, as we want to show the color
// before the item is considered selected, and hence before the new contentColor is
// provided by BottomNavigationTransition.
val ripple = rememberRipple(bounded = false, color = selectedContentColor)
Box(
modifier
.selectable(
selected = selected,
onClick = onClick,
enabled = enabled,
role = Role.Tab,
interactionSource = interactionSource,
indication = ripple
)
.weight(1f),
contentAlignment = Alignment.Center
) {
BottomNavigationTransition(
selectedContentColor,
unselectedContentColor,
selected
) { progress ->
val animationProgress = if (alwaysShowLabel) 1f else progress
BottomNavigationItemBaselineLayout(
icon = icon,
label = styledLabel,
iconPositionAnimationProgress = animationProgress
)
}
}
}
或者这会打断例如触摸动画作为新的 NavigationBar 在切换屏幕时被实例化?
这取决于调用的动画类型,因为当屏幕进入组合时,新的 BottomNavigation 可组合项将在每个屏幕上调用。
如果你有一个动画,当一个项目被点击时开始,例如,需要一秒钟才能完成,在新页面上,你可能会看到目标索引在目标页面中被选中,而你可能希望这个动画继续,因为它只在一页。
@Composable
fun BottomNavigationComponent() {
var selectedIndex by remember { mutableStateOf(1) }
val tabContents = listOf(
"Home" to Icons.Filled.Home,
"Map" to Icons.Filled.Map,
"Settings" to Icons.Filled.Settings
)
BottomNavigation(
backgroundColor = MaterialTheme.colors.surface,
contentColor = MaterialTheme.colors.onSurface,
elevation = 2.dp
) {
tabContents.forEachIndexed { index, pair: Pair<String, ImageVector> ->
BottomNavigationItem(
icon = { Icon(pair.second, contentDescription = null) },
label = { Text(pair.first) },
selected = selectedIndex == index,
alwaysShowLabel = false, // Hides the title for the unselected items
onClick = {
selectedIndex = index
}
)
}
}
}