android 我们能在每个屏幕上都有一个NavigationBar示例而没有功能上的缺点吗?

fae0ux8s  于 2023-04-28  发布在  Android
关注(0)|答案(1)|浏览(178)

bounty还有3天到期。回答此问题可获得+200声望奖励。stefan.at.kotlin希望引起更多关注此问题。

当使用Jetpack Compose和Material Design时,是否可以在每个屏幕上使用新的NavigationBar(又名BottomNavigationBar)?或者这会中断例如触摸动画,因为在切换屏幕时新的NavigationBar被示例化?
我的想法是,这真的可以很容易地在某些屏幕上隐藏或显示NavigationBar,而不是在其他屏幕上(而不是与层次结构中更高的Scaffold进行通信)

9jyewag0

9jyewag01#

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类似于在任何屏幕上使用另一个Composable。此外,当标签和图标都存在时,BottomNavigationItem只是一个Box或两个Box

@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
                }
            )
        }
    }
}

相关问题