You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Android Jetpack Compose中实现带圆角效果的底部导航栏

实现方案

核心思路

Jetpack Compose的NavigationBar(Material3组件)本身支持自定义形状属性,只需要给它配置圆角形状,再调整布局边距就能实现你要的效果。

具体实现步骤

  • 首先确保你项目中已经引入了Compose Material3依赖:
implementation "androidx.compose.material3:material3:1.2.1"
  • 然后在布局中自定义NavigationBar的shape属性,同时可以根据需求加边距实现悬浮效果,完整参考代码如下:
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Home
import androidx.compose.material.icons.filled.Message
import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.Message
import androidx.compose.material.icons.outlined.Person
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.navigation.NavDestination.Companion.hierarchy
import androidx.navigation.NavGraph.Companion.findStartDestination
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController

@Composable
fun RoundedBottomNavigationDemo() {
    val navController = rememberNavController()
    // 底部导航路由列表,按需替换为你自己的页面配置
    val navItems = listOf(
        NavItem.Home,
        NavItem.Message,
        NavItem.Profile
    )
    Scaffold(
        bottomBar = {
            NavigationBar(
                // 核心配置:设置圆角,仅要顶部圆角就只配置topStart和topEnd,要悬浮款就传统一圆角值
                shape = RoundedCornerShape(topStart = 24.dp, topEnd = 24.dp),
                modifier = Modifier
                    // 悬浮款额外加左右和底部边距即可
                    .padding(horizontal = 12.dp, bottom = 18.dp)
                    // 自定义阴影时圆角要和上方shape保持一致
                    .shadow(elevation = 8.dp, shape = RoundedCornerShape(24.dp)),
                containerColor = Color.White,
                contentColor = MaterialTheme.colorScheme.primary
            ) {
                val currentBackStackEntry by navController.currentBackStackEntryAsState()
                val currentDestination = currentBackStackEntry?.destination
                navItems.forEach { item ->
                    val isSelected = currentDestination?.hierarchy?.any { it.route == item.route } == true
                    NavigationBarItem(
                        selected = isSelected,
                        onClick = {
                            navController.navigate(item.route) {
                                popUpTo(navController.graph.findStartDestination().id)
                                launchSingleTop = true
                            }
                        },
                        icon = {
                            Icon(
                                imageVector = if (isSelected) item.selectedIcon else item.unselectedIcon,
                                contentDescription = item.label
                            )
                        },
                        label = { Text(item.label) }
                    )
                }
            }
        }
    ) { innerPadding ->
        // 页面内容区域,记得应用innerPadding避免内容和导航栏重叠
        NavHost(
            navController = navController,
            startDestination = NavItem.Home.route,
            modifier = Modifier.padding(innerPadding)
        ) {
            // 注册你的页面路由,替换为实际页面组件
            composable(NavItem.Home.route) { /* 首页组件 */ }
            composable(NavItem.Message.route) { /* 消息页组件 */ }
            composable(NavItem.Profile.route) { /* 个人页组件 */ }
        }
    }
}

// 示例导航项实体类,按需修改
sealed class NavItem(
    val route: String,
    val label: String,
    val selectedIcon: ImageVector,
    val unselectedIcon: ImageVector
) {
    object Home : NavItem(
        route = "home",
        label = "首页",
        selectedIcon = Icons.Filled.Home,
        unselectedIcon = Icons.Outlined.Home
    )
    object Message : NavItem(
        route = "message",
        label = "消息",
        selectedIcon = Icons.Filled.Message,
        unselectedIcon = Icons.Outlined.Message
    )
    object Profile : NavItem(
        route = "profile",
        label = "我的",
        selectedIcon = Icons.Filled.Person,
        unselectedIcon = Icons.Outlined.Person
    )
}

注意事项

  • 如果出现导航栏和系统底部手势导航条重叠的问题,可以给NavigationBar的modifier追加navigationBarsPadding(),自动适配系统底部边距。
  • 圆角数值、阴影大小、边距数值都可以根据你的设计稿需求灵活调整。

内容的提问来源于stack exchange,提问作者Oğuzhan Aslan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 12:06:04