Reputation: 3440
Created a simple Jetpack Compose app straight out of the Android Studio template and added a bottom navigation bar. Did not specify/override any color anywhere. However, bottom nav bar labels show black-on-purple. I did not change ui/theme/Color.kt. Dark mode not enabled in the device.
I need to change the label text color contrasting to the background (depending up light/dark mode etc.). Where and how do I configure this?
Manifest refers to theme:
<style name="Theme.MyApp" parent="android:Theme.Material.Light.NoActionBar" />
Here is the code:
setContent {
MyAppTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val homeViewModel: HomeViewModel by viewModels()
val navController = rememberNavController()
val items = listOf(
Screen.Home,
Screen.Profile,
)
Scaffold(
bottomBar = {
BottomNavigation {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
items.forEach { screen ->
BottomNavigationItem(
icon = { Icon(screen.icon, contentDescription = null) },
label = {
Text(
stringResource(screen.resourceId),
style = Typography.labelSmall
)
},
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
)
}
}
}
)
}
}
}
Upvotes: 2
Views: 4362
Reputation: 379
To modify the bottom navigation bar colors from the Theme, you need to fill the following parameters on your ColorScheme
:
private val LightColorScheme = lightColorScheme(
...
surfaceContainer = Color(0xFF...), // Background navigation bar color
onSurface = Color(0xFF...), // Selected color (label)
onSurfaceVariant = Color(0xFF...), // Unselected (label, icon)
onSecondaryContainer = Color(0xFF...), // Selected color (icon)
secondaryContainer = Color(0xFF...), // Icon box (appear when selected)
...
)
Pay attention that the tonalElevation
parameter can also change navigation bar color:
NavigationBar(tonalElevation = 0.dp) {
...
}
EDIT: bumped Compose BOM to 2024.11.00
and now the property that defines the background color is surfaceContainer
(instead of surface
)
Upvotes: 0
Reputation: 1283
If you're Implementing BottomBar in Compose UI:
By reference to the below you can modify the colors of your choice.
Note: The tabs here are only the list you can modify and take necessary things out of it.
val btmBrClr = Color(0xFF3B3B3B)
BottomAppBar(containerColor = btmBrClr) {
tabs.forEach {
NavigationBarItem(
selected = currentTab == it.tab,
onClick = {
currentTab = it.tab
},
icon = {
Icon(
painter = painterResource(id = it.image),
contentDescription = it.name
)
},
label = { Text(text = it.name) },
colors = NavigationBarItemDefaults.colors(
selectedIconColor = MaterialTheme.colorScheme.onPrimary,
unselectedIconColor = MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.5f),
selectedTextColor = MaterialTheme.colorScheme.onPrimary,
unselectedTextColor = MaterialTheme.colorScheme.onPrimary.copy(alpha = 0.5f),
indicatorColor = btmBrClr
)
)
}
}
Upvotes: 0
Reputation: 2214
First you need to define/support dynamic theme in your compose app:
AppTheme.kt
@Composable
fun MainAppTheme(
isDarkMode: Boolean,
content: @Composable () -> Unit
) {
MaterialTheme(colorScheme = if (isDarkMode) themeDarkColorScheme else themeLightColorScheme) {
CompositionLocalProvider(
LocalDarkMode provides isDarkMode,
LocalAppColorScheme provides if (isDarkMode) appDarkColorScheme else appLightColorScheme,
content = content
)
}
}
object AppTheme {
val colorScheme: AppColorScheme
@Composable
@ReadOnlyComposable
get() = LocalAppColorScheme.current
}
AppColorScheme.kt
private val primaryColor = Color(0xFFFF9800)
private val secondaryLightColor = Color(0xFF34495E)
private val secondaryVariantLightColor = Color(0x5234495E)
private val secondaryDarkColor = Color(0xFFCEE5FF)
private val secondaryVariantDarkColor = Color(0x66CEE5FF)
private val tertiaryDarkColor = Color(0xFF58633A)
private val tertiaryLightColor = Color(0xFFDCE8B4)
private val containerHighLightColor = Color(0x2934495E)
private val containerNormalLightColor = Color(0x1434495E)
private val containerLowLightColor = Color(0x0A34495E)
private val containerHighDarkColor = Color(0x3DCEE5FF)
private val containerNormalDarkColor = Color(0x29CEE5FF)
private val containerLowDarkColor = Color(0x14CEE5FF)
private val textPrimaryLightColor = Color(0xDE000000)
private val textSecondaryLightColor = Color(0x99000000)
private val textDisabledLightColor = Color(0x66000000)
private val textPrimaryDarkColor = Color(0xFFFFFFFF)
private val textSecondaryDarkColor = Color(0xCCFFFFFF)
private val textDisabledDarkColor = Color(0x99FFFFFF)
private val outlineLightColor = Color(0x14000000)
private val outlineDarkColor = Color(0x14FFFFFF)
private val surfaceLightColor = Color(0xFFFFFFFF)
private val surfaceDarkColor = Color(0xFF121212)
private val awarenessAlertColor = Color(0xFFCA2F27)
private val awarenessPositiveColor = Color(0xFF47A96E)
private val awarenessWarningColor = Color(0xFFD39800)
internal val themeLightColorScheme = lightColorScheme().copy(
primary = primaryColor,
onPrimary = textPrimaryLightColor,
background = surfaceLightColor,
onBackground = textPrimaryLightColor,
onSecondary = textPrimaryLightColor
)
internal val appLightColorScheme = AppColorScheme(
primary = primaryColor,
secondary = secondaryLightColor,
secondaryVariant = secondaryVariantLightColor,
tertiary = tertiaryDarkColor,
tertiaryVariant = tertiaryLightColor,
outline = outlineLightColor,
surface = surfaceLightColor,
textPrimary = textPrimaryLightColor,
textSecondary = textSecondaryLightColor,
textDisabled = textDisabledLightColor,
outlineInverse = outlineDarkColor,
textInversePrimary = textPrimaryDarkColor,
textInverseDisabled = textDisabledDarkColor,
textInverseSecondary = textSecondaryDarkColor,
containerInverseHigh = containerHighDarkColor,
containerNormalInverse = containerNormalDarkColor,
secondaryInverseVariant = secondaryVariantDarkColor,
containerHigh = containerHighLightColor,
containerNormal = containerNormalLightColor,
containerLow = containerLowLightColor
)
internal val themeDarkColorScheme = darkColorScheme().copy(
primary = primaryColor,
onPrimary = textPrimaryDarkColor,
background = surfaceDarkColor,
onBackground = textPrimaryDarkColor,
onSecondary = textPrimaryDarkColor
)
internal val appDarkColorScheme = AppColorScheme(
primary = primaryColor,
secondary = secondaryDarkColor,
secondaryVariant = secondaryVariantDarkColor,
tertiary = tertiaryLightColor,
tertiaryVariant = tertiaryDarkColor,
outline = outlineDarkColor,
surface = surfaceDarkColor,
textPrimary = textPrimaryDarkColor,
textSecondary = textSecondaryDarkColor,
textDisabled = textDisabledDarkColor,
outlineInverse = outlineLightColor,
textInversePrimary = textPrimaryLightColor,
textInverseDisabled = textDisabledLightColor,
textInverseSecondary = textSecondaryLightColor,
containerInverseHigh = containerHighLightColor,
containerNormalInverse = containerNormalLightColor,
secondaryInverseVariant = secondaryVariantLightColor,
containerHigh = containerHighDarkColor,
containerNormal = containerNormalDarkColor,
containerLow = containerLowDarkColor
)
val LocalDarkMode = staticCompositionLocalOf {
false
}
val LocalAppColorScheme = staticCompositionLocalOf {
appLightColorScheme
}
data class AppColorScheme(
val primary: Color,
val tertiary: Color,
val tertiaryVariant: Color,
val secondary: Color,
val secondaryVariant: Color,
val surface: Color,
val outline: Color,
val textPrimary: Color,
val textSecondary: Color,
val textDisabled: Color,
val outlineInverse: Color,
val textInversePrimary: Color,
val textInverseSecondary: Color,
val textInverseDisabled: Color,
val containerInverseHigh: Color,
val containerNormalInverse: Color,
val secondaryInverseVariant: Color,
val containerHigh: Color,
val containerNormal: Color,
val containerLow: Color,
val positive: Color = awarenessPositiveColor,
val alert: Color = awarenessAlertColor,
val warning: Color = awarenessWarningColor,
val onPrimary: Color = textPrimaryDarkColor,
val onPrimaryVariant: Color = textPrimaryLightColor,
val onSecondary: Color = textSecondaryDarkColor,
val onDisabled: Color = textDisabledLightColor
) {
val containerNormalOnSurface: Color
get() {
return containerNormal.compositeOver(surface)
}
}
Now apply this MainAppTheme in place of MyAppTheme
:
setContent {
// Apply your logic to toggle darkMode/lightMode conditions. This is basic one
val isDarkModeEnabled = when (resources?.configuration?.uiMode?.and(UI_MODE_NIGHT_MASK)) {
UI_MODE_NIGHT_YES, UI_MODE_NIGHT_UNDEFINED -> {
true
}
UI_MODE_NIGHT_NO -> {
false
}
}
MainAppTheme(isDarkMode = isDarkModeEnabled) {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
val homeViewModel: HomeViewModel by viewModels()
val navController = rememberNavController()
val items = listOf(
Screen.Home,
Screen.Profile,
)
Scaffold(
bottomBar = {
BottomNavigation(
backgroundColor = AppTheme.colorScheme.containerNormalOnSurface,
contentColor = AppTheme.colorScheme.primary
) {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
items.forEach { screen ->
BottomNavigationItem(
icon = { Icon(screen.icon, contentDescription = null) },
label = {
Text(
stringResource(screen.resourceId),
style = Typography.labelSmall
)
},
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
selectedContentColor = **Specify color**,
unselectedContentColor = **Specify color**,
onClick = {
navController.navigate(screen.route) {
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
launchSingleTop = true
restoreState = true
}
},
)
}
}
}
)
}
}
}
Upvotes: 3
Reputation: 29
You can use backgroundColor and contentColor like below:
BottomNavigation(
modifier: Modifier = Modifier,
backgroundColor: Color = MaterialTheme.colors.primarySurface,
contentColor: Color = contentColorFor(backgroundColor),
elevation: Dp = BottomNavigationDefaults.Elevation,
content: @Composable RowScope.() -> Unit
)
Upvotes: 0