J'ai 2 écrans qui ont tous les deux leur propre Scaffold
et TopAppBar
. Lorsque je navigue entre eux à l'aide de la bibliothèque de la composition de navigation Jetpack, la barre d'application clignote. Pourquoi cela se passe-t-il et comment puis-je me débarrasser de cela?
Code:
La navigation:
@Composable
fun TodoNavHost(
navController: NavHostController,
modifier: Modifier = Modifier
) {
NavHost(
navController = navController,
startDestination = TodoScreen.TodoList.name,
modifier = modifier
) {
composable(TodoScreen.TodoList.name) {
TodoListScreen(
onTodoEditClicked = { todo ->
navController.navigate("${TodoScreen.AddEditTodo.name}?todoId=${todo.id}")
},
onFabAddNewTodoClicked = {
navController.navigate(TodoScreen.AddEditTodo.name)
}
)
}
composable(
"${TodoScreen.AddEditTodo.name}?todoId={todoId}",
arguments = listOf(
navArgument("todoId") {
type = NavType.LongType
defaultValue = -1L
}
)
) {
AddEditTodoScreen(
onNavigateUp = {
navController.popBackStack()
},
onNavigateBackWithResult = { result ->
navController.navigate(TodoScreen.TodoList.name)
}
)
}
}
}
Écran de liste TODO Scaffold
avec TopAppBar
:
@Composable
fun TodoListBody(
todos: List<Todo>,
todoExpandedStates: Map<Long, Boolean>,
onTodoItemClicked: (Todo) -> Unit,
onTodoCheckedChanged: (Todo, Boolean) -> Unit,
onTodoEditClicked: (Todo) -> Unit,
onFabAddNewTodoClicked: () -> Unit,
onDeleteAllCompletedConfirmed: () -> Unit,
modifier: Modifier = Modifier,
errorSnackbarMessage: String = "",
errorSnackbarShown: Boolean = false
) {
var menuExpanded by remember { mutableStateOf(false) }
var showDeleteAllCompletedConfirmationDialog by rememberSaveable { mutableStateOf(false) }
Scaffold(
modifier,
topBar = {
TopAppBar(
title = { Text("My Todos") },
actions = {
IconButton(
onClick = { menuExpanded = !menuExpanded },
modifier = Modifier.semantics {
contentDescription = "Options Menu"
}
) {
Icon(Icons.Default.MoreVert, contentDescription = "Show menu")
}
DropdownMenu(
expanded = menuExpanded,
onDismissRequest = { menuExpanded = false }) {
DropdownMenuItem(
onClick = {
showDeleteAllCompletedConfirmationDialog = true
menuExpanded = false
},
modifier = Modifier.semantics {
contentDescription = "Option Delete All Completed"
}) {
Text("Delete all completed")
}
}
}
)
},
[...]
Ajouter/Modifier l'écran Scaffold
avec TopAppBar
:
@Composable
fun AddEditTodoBody(
todo: Todo?,
todoTitle: String,
setTitle: (String) -> Unit,
todoImportance: Boolean,
setImportance: (Boolean) -> Unit,
onSaveClick: () -> Unit,
onNavigateUp: () -> Unit,
modifier: Modifier = Modifier
) {
Scaffold(
modifier,
topBar = {
TopAppBar(
title = { Text(todo?.let { "Edit Todo" } ?: "Add Todo") },
actions = {
IconButton(onClick = onSaveClick) {
Icon(Icons.Default.Save, contentDescription = "Save Todo")
}
},
navigationIcon = {
IconButton(onClick = onNavigateUp) {
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
}
}
)
},
) { innerPadding ->
BodyContent(
todoTitle = todoTitle,
setTitle = setTitle,
todoImportance = todoImportance,
setImportance = setImportance,
modifier = Modifier.padding(innerPadding)
)
}
}
Le clignotant est causé par l'animation transversale par défaut dans des versions plus récentes de la navigation-compose
bibliothèque. Le seul moyen de s'en débarrasser en ce moment (sans déclasser la dépendance) consiste à utiliser l'accompagnateur Bibliothèque d'animation:
implementation "com.google.accompanist:accompanist-navigation-animation:0.20.0"
puis remplacer la normale NavHost
pour l'accompagnateur AnimatedNavHost
et désactiver les animations de transition:
AnimatedNavHost(
navController = navController,
startDestination = bottomNavDestinations[0].fullRoute,
enterTransition = { _, _ -> EnterTransition.None },
exitTransition = { _, _ -> ExitTransition.None },
popEnterTransition = { _, _ -> EnterTransition.None },
popExitTransition = { _, _ -> ExitTransition.None },
modifier = modifier,
) {
[...}
}
J'ai eu le même problème ayant une architecture "échafaudeuse par écran". Ce qui a aidé, à ma surprise, réduisait androidx.navigation:navigation-compose
Version à 2.4.0-alpha04
.
C'est le comportement attendu. Vous construisez deux barres d'applications distinctes pour les deux écrans afin qu'ils soient liés à clignoter. Ce n'est pas la bonne façon. La bonne façon serait de mettre l'échafaudage dans votre activité principale et de placer la Navhost en tant que contenu. Si vous souhaitez modifier la barre d'application, créez des variables pour conserver l'état. Puis modifiez-les des compossables. Idéalement, stockez ensuite dans une vue de vue. C'est ainsi que cela se fait dans la composition. À travers les variables.
Merci