Reputation: 119
I'm trying to set an icon for bottom navigation like so:
sealed class Screen(val route: String, val label: String, val icon: ImageVector) {
object Home : Screen("home", "Home",R.drawable.outline_home_black_24)
object History : Screen("history", "History", R.drawable.outline_history_black_24)
}
But it says I need to switch the parameter to Int. Help is appreciated, thanks. :)
Upvotes: 4
Views: 11359
Reputation: 773
You can convert your xml resource into Compose ImageVector
using Valkyrie
and set it into Icon
Icon(imageVector = YourIcon, contentDescription = null)
Upvotes: 1
Reputation: 2228
You should use ImageVector.vectorResource function like this:
import androidx.compose.ui.res.vectorResource
sealed class Screen(val route: String, val label: String, val icon: ImageVector) {
object Home : Screen("home", "Home",ImageVector.vectorResource(R.drawable.outline_home_black_24))
object History : Screen("history", "History", ImageVector.vectorResource(R.drawable.outline_history_black_24))
}
Upvotes: 10
Reputation: 143
Not quite the answer for the question in place, but, maybe can help someone in need...
If you are using Jetpack Compose and want flexibility between using ImageVector
, as Icons.Filled.Favorite
and using a drawable resource, you can achieve this by using a helper class, like the following:
class IconResource private constructor(
@DrawableRes private val resID: Int?,
private val imageVector: ImageVector?
) {
@Composable
fun asPainterResource(): Painter {
resID?.let {
return painterResource(id = resID)
}
return rememberVectorPainter(image = imageVector!!)
}
companion object {
fun fromDrawableResource(@DrawableRes resID: Int): IconResource {
return IconResource(resID, null)
}
fun fromImageVector(imageVector: ImageVector?): IconResource {
return IconResource(null, imageVector)
}
}
}
With that class you can create your sealed class accordingly:
sealed class Screen(val route: String, @StringRes val resourceId: Int, icon: IconResource) {
object Home : Screen(
"home", R.string.something,
IconResource.fromDrawableResource(R.drawable.outline_home_black_24)
)
object History : Screen(
"history", R.string.something,
IconResource.fromImageVector(Icons.Filled.Favorite)
)
}
Then, just call in your composable:
navigationItems.forEach { screen ->
BottomNavigationItem(icon = {
Icon(
screen.icon.asPainterResource(),
contentDescription = null
)
}
...
}
I've released a lib with that implementation, if you need it, can be found here: https://github.com/ygorluizfrazao/compose-resources
Hope it helps.
Upvotes: 8
Reputation: 352
Try this
sealed class Screen(val route: String, val label: String, val icon: ImageVector) {
object Home : Screen("home", "Home", painterResource(id = R.drawable.outline_home_black_24))
object History : Screen("history", "History", painterResource(id = R.drawable.outline_history_black_24))
}
Upvotes: 2
Reputation: 1345
Yes. Refrences like R.drawable.outline_home_black_24
is not the actual ImageVector
but Int references to help get them in code. To get the actual image you should use something like ContextCompat.getDrawable(context, R.drawable.***)
to get the actual Drawable
file. This means that the correct usage should be
sealed class Screen(val route: String, val label: String, @DrawableRes val icon: Int)
The extra annotation throws a warning if a drawable resource which is something like R.drawable.***
is not passed
Upvotes: 3