https://kotlinlang.org logo
#compose
Title
# compose
l

Luca Nicoletti

07/06/2023, 12:25 PM
I have a
BottomNavigationBar
as follow:
Copy code
BottomNavigation(
   Modifier
      .fillMaxWidth()
      .height(64.dp),
   backgroundColor = Colors.surface,
) {
   items.forEach { screen ->
      val selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true
      BottomNavigationItem(
         icon = { Icon(painterResource(screen.getIcon()), contentDescription = null) },
         selected = selected,
         selectedContentColor = Color.Blue,
         unselectedContentColor = Color.Cyan,
         label = {
            Text(text = stringResource(id = screen.label), fontSize = 11.sp, color = Color.Gray)
         },
         onClick = { onClick(screen) }
      )
   }
}
But this doesn’t colour (both selected & unselected are ignored) the icons, what am I doing wrong?
selected
is calculated correctly for every item
Copy code
val color = if (selected) {
                Colors.bottomBarSelectedColor
            } else {
                Colors.gray
            }
            BottomNavigationItem(
                icon = { Icon(painterResource(id = screen.getIcon()), null, tint = color) },
This works, but I would expect it to work out of the box? Am I missing something? 🙂
s

Stylianos Gakis

07/06/2023, 1:14 PM
Where does
BottomNavigationItem
come from? What does it do with the colors inside there when it’s passed? Could it be smth silly like using the LocalContentColor from material2 while you’re using the Icon from material3 so it doesn’t pick the composition local correctly for the tint parameter?
l

Luca Nicoletti

07/06/2023, 1:19 PM
package androidx.compose.materi
Looking inside the code, doesn’t seem like they’re touching the icon you provide at all
s

Stylianos Gakis

07/06/2023, 1:26 PM
Yeah they pass the content color to the surface though, which sets the LocalContentColor, which the Icon composable uses as the default parameter for tint
l

Luca Nicoletti

07/06/2023, 1:33 PM
I don’t see where a Surface is used tbh
s

Stylianos Gakis

07/06/2023, 1:37 PM
Aha, I was looking in the material3 one, but you are probably using the material2 one, which as you say does not use Surface. https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]ose/material/BottomNavigation.kt;l=147?q=BottomNavigationItem What they do there instead is in here animate the color between the two colors you give them, and pass it down in the
LocalContentColor
. And then Icon here takes that LocalContentColor to decide what the tint is. So my guess it you’re using Icon from material3. The only other explanation would be that your icon isn’t able to be tinted correctly, but it doesn’t seem the case since specifically chosing the right color does seem to work for you. So check if you do
import androidx.compose.material3.Icon
in that file.
l

Luca Nicoletti

07/06/2023, 1:39 PM
Hero!
Thanks, switching to icon (not material3) solved it, looking now to switch everything to material3 though 🙂
s

Stylianos Gakis

07/06/2023, 1:44 PM
Then you need to switch both to Material3, so it sets the correct LocalContentColor local, and then the Icon will also fetch it from the right place too. material3 locals play well with material3 components and the same goes for material2. If you need your own custom components to support both cases in case someone passes in a material2 component to your custom composable for example, you’d need to do something like this for example, to set the locals for both m2 and m3, both local content colors, but also TextStyle in this case since I was making a button component. I’ve had this situation come up a lot in the migration from m2->m3, so now it’s easy to spot 😅
3 Views