如果在 android jetpack compose 中选择和取消选择,如何更改图标,就像我们在 xml 中用于选择状态的选择器一样?
How to change icon if selected and unselected in android jetpack compose for NavigationBar like selector we use in xml for selected state?
-
android
-
material-components-android
-
android-jetpack-compose
-
android-jetpack-compose-scaffold
-
jetpack-compose-navigation
我想在 NavigationBar 中使用基于选定状态的轮廓和填充图标,就像 google 地图应用程序一样,使用 Jetpack Compose。在 xml 的情况下,我们使用选择器,那么我们用什么来撰写?
这是我的代码 ->
MainActivity.kt
@ExperimentalMaterial3Api
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Handle the splash screen transition.
installSplashScreen()
setContent {
MyApp()
}
}
}
@ExperimentalMaterial3Api
@Composable
fun MyApp() {
MyTheme {
val items = listOf(
Screen.HomeScreen,
Screen.MusicScreen,
Screen.ProfileScreen
)
val navController = rememberNavController()
Scaffold(
bottomBar = {
NavigationBar {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
items.forEach { screen ->
NavigationBarItem(
icon = {
Icon(
screen.icon_outlined,
contentDescription = screen.label.toString()
)
},
label = { Text(stringResource(screen.label)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
}
}
}
) { innerPadding ->
NavHost(
navController,
startDestination = Screen.HomeScreen.route,
Modifier.padding(innerPadding)
) {
composable(route = Screen.HomeScreen.route) {
HomeScreen()
}
composable(route = Screen.MusicScreen.route) {
MusicScreen()
}
composable(route = Screen.ProfileScreen.route) {
ProfileScreen()
}
}
}
}
}
@ExperimentalMaterial3Api
@Preview(
showBackground = true, name = "Light mode",
uiMode = Configuration.UI_MODE_NIGHT_NO or Configuration.UI_MODE_TYPE_NORMAL
)
@Preview(
showBackground = true, name = "Night mode",
uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL
)
@Composable
fun DefaultPreview() {
MyApp()
}
Screen.kt
sealed class Screen(
val route: String,
@StringRes val label: Int,
val icon_outlined: ImageVector,
val icon_filled: ImageVector
) {
object HomeScreen : Screen(
route = "home_screen",
label = R.string.home,
icon_outlined = Icons.Outlined.Home,
icon_filled = Icons.Filled.Home
)
object MusicScreen : Screen(
route = "music_screen",
label = R.string.music,
icon_outlined = Icons.Outlined.LibraryMusic,
icon_filled = Icons.Filled.LibraryMusic,
)
object ProfileScreen : Screen(
route = "profile_screen",
label = R.string.profile,
icon_outlined = Icons.Outlined.AccountCircle,
icon_filled = Icons.Filled.AccountCircle,
)
}
主页Screen.kt
@Composable
fun HomeScreen() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Surface(color = MaterialTheme.colorScheme.background) {
Text(
text = "Home",
color = Color.Red,
fontSize = MaterialTheme.typography.displayLarge.fontSize,
fontWeight = FontWeight.Bold
)
}
}
}
@Preview(
showBackground = true, name = "Light mode",
uiMode = Configuration.UI_MODE_NIGHT_NO or Configuration.UI_MODE_TYPE_NORMAL
)
@Preview(
showBackground = true, name = "Night mode",
uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL
)
@Composable
fun HomeScreenPreview() {
HomeScreen()
}
我还需要使用选择器 xml 还是在 Jetpack Compose 中有替代方法?
是的,你只需要根据selected
状态做一个简单的if语句,像这样:
items.forEach { screen ->
val selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true
NavigationBarItem(
icon = {
Icon(
if (selected) screen.icon_filled else screen.icon_outlined,
contentDescription = screen.label.toString()
)
},
selected = selected,
)
}
android
material-components-android
android-jetpack-compose
android-jetpack-compose-scaffold
jetpack-compose-navigation
我想在 NavigationBar 中使用基于选定状态的轮廓和填充图标,就像 google 地图应用程序一样,使用 Jetpack Compose。在 xml 的情况下,我们使用选择器,那么我们用什么来撰写?
这是我的代码 ->
MainActivity.kt
@ExperimentalMaterial3Api
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// Handle the splash screen transition.
installSplashScreen()
setContent {
MyApp()
}
}
}
@ExperimentalMaterial3Api
@Composable
fun MyApp() {
MyTheme {
val items = listOf(
Screen.HomeScreen,
Screen.MusicScreen,
Screen.ProfileScreen
)
val navController = rememberNavController()
Scaffold(
bottomBar = {
NavigationBar {
val navBackStackEntry by navController.currentBackStackEntryAsState()
val currentDestination = navBackStackEntry?.destination
items.forEach { screen ->
NavigationBarItem(
icon = {
Icon(
screen.icon_outlined,
contentDescription = screen.label.toString()
)
},
label = { Text(stringResource(screen.label)) },
selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true,
onClick = {
navController.navigate(screen.route) {
// Pop up to the start destination of the graph to
// avoid building up a large stack of destinations
// on the back stack as users select items
popUpTo(navController.graph.findStartDestination().id) {
saveState = true
}
// Avoid multiple copies of the same destination when
// reselecting the same item
launchSingleTop = true
// Restore state when reselecting a previously selected item
restoreState = true
}
}
)
}
}
}
) { innerPadding ->
NavHost(
navController,
startDestination = Screen.HomeScreen.route,
Modifier.padding(innerPadding)
) {
composable(route = Screen.HomeScreen.route) {
HomeScreen()
}
composable(route = Screen.MusicScreen.route) {
MusicScreen()
}
composable(route = Screen.ProfileScreen.route) {
ProfileScreen()
}
}
}
}
}
@ExperimentalMaterial3Api
@Preview(
showBackground = true, name = "Light mode",
uiMode = Configuration.UI_MODE_NIGHT_NO or Configuration.UI_MODE_TYPE_NORMAL
)
@Preview(
showBackground = true, name = "Night mode",
uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL
)
@Composable
fun DefaultPreview() {
MyApp()
}
Screen.kt
sealed class Screen(
val route: String,
@StringRes val label: Int,
val icon_outlined: ImageVector,
val icon_filled: ImageVector
) {
object HomeScreen : Screen(
route = "home_screen",
label = R.string.home,
icon_outlined = Icons.Outlined.Home,
icon_filled = Icons.Filled.Home
)
object MusicScreen : Screen(
route = "music_screen",
label = R.string.music,
icon_outlined = Icons.Outlined.LibraryMusic,
icon_filled = Icons.Filled.LibraryMusic,
)
object ProfileScreen : Screen(
route = "profile_screen",
label = R.string.profile,
icon_outlined = Icons.Outlined.AccountCircle,
icon_filled = Icons.Filled.AccountCircle,
)
}
主页Screen.kt
@Composable
fun HomeScreen() {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Surface(color = MaterialTheme.colorScheme.background) {
Text(
text = "Home",
color = Color.Red,
fontSize = MaterialTheme.typography.displayLarge.fontSize,
fontWeight = FontWeight.Bold
)
}
}
}
@Preview(
showBackground = true, name = "Light mode",
uiMode = Configuration.UI_MODE_NIGHT_NO or Configuration.UI_MODE_TYPE_NORMAL
)
@Preview(
showBackground = true, name = "Night mode",
uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL
)
@Composable
fun HomeScreenPreview() {
HomeScreen()
}
我还需要使用选择器 xml 还是在 Jetpack Compose 中有替代方法?
是的,你只需要根据selected
状态做一个简单的if语句,像这样:
items.forEach { screen ->
val selected = currentDestination?.hierarchy?.any { it.route == screen.route } == true
NavigationBarItem(
icon = {
Icon(
if (selected) screen.icon_filled else screen.icon_outlined,
contentDescription = screen.label.toString()
)
},
selected = selected,
)
}