web-dev-qa-db-fra.com

TopAppar clignotant lors de la navigation avec une navigation de composition

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?

enter image description here

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)
        )
    }
}
5
Florian Walther

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,
    ) {
        [...}
    }
0
Florian Walther

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.

1
Artur Popławski

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

0
MARSK