当前位置: 首页 > 知识库问答 >
问题:

使用撰写导航进行导航时顶部应用栏闪烁

严正初
2023-03-14

我有2个屏幕,它们都有自己的脚手架TopAppBar。当我使用 Jetpack Navigation Compose 库在它们之间导航时,应用栏会闪烁。为什么会发生这种情况,我该如何摆脱这种情况?

法典:

导航:

@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)
                }
            )
        }
    }
}

Todo列表屏幕<代码>脚手架<代码>带有<代码>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")
                        }
                    }
                }

            )
        },
[...]

使用 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)
        )
    }
}

共有3个答案

和丰羽
2023-03-14

这是预期的行为。您正在为两个屏幕构建两个单独的应用程序栏,因此它们肯定会闪烁。这不是正确的方法。正确的方法是将脚手架实际放在您的主活动中,并将NavHost作为其内容放置。如果您希望修改应用程序栏,请创建变量以保存状态。然后从Composables中修改它们。理想情况下,将其存储在视图模型中。这就是Compose中的操作方式。通过变量

谢谢

冯翔
2023-03-14

我想我为这个问题找到了一个简单的解决方案(适用于Compose版本1.4.0)。

我的所有屏幕都有自己的工具条,包裹在脚手架中:

// Some Composable screnn

Scaffold(
    topBar = { TopAppBar(...) }
) {
    ScreenContent()
}

持有导航主机的主要活动定义如下:

// Activity with NavHost

setContent {
    AppTheme {
        NavHost(...) { }
    }
}

将 NavHost 包装在 Surface 中的活动中:

setContent {
    AppTheme {
        Surface {
            NavHost(...) { }
        }
    }
}

其余的屏幕保持不变。目的地之间没有闪烁和过渡动画几乎和碎片一样(微妙的淡入/淡出)。到目前为止,我还没有发现任何负面影响。

曹嘉许
2023-03-14

闪烁是由较新版本的导航组合库中的默认交叉淡入淡出动画引起的。现在摆脱它的唯一方法(不降低依赖关系)是使用Accompanist动画库:

< code >实现" com.google .伴奏者:伴奏者-导航-动画:0.20.0"

然后将正常的 NavHost 替换为 Accompanist 的 AnimatedNavHost,将 rememberNavController() 替换为 rememberAnimatedNavController() 并禁用过渡动画:

AnimatedNavHost(
        navController = navController,
        startDestination = bottomNavDestinations[0].fullRoute,
        enterTransition = { _, _ -> EnterTransition.None },
        exitTransition = { _, _ -> ExitTransition.None },
        popEnterTransition = { _, _ -> EnterTransition.None },
        popExitTransition = { _, _ -> ExitTransition.None },
        modifier = modifier,
    ) {
        [...}
    }
 类似资料:
  • 顶部导航栏放在页面头部: 实例<nav data-topbar>   <ul>     <li>       <!-- 如果你不需要标题或图标可以删掉它 -->       <h1><a href="#">WebSiteName</a></h1>     </li>       <!-- 小屏幕上折叠按钮: 去掉 .menu-icon 类,可以去除图标。       如果需要只显示图片,可以删除

  • 使用数据查看器的“导航栏”按钮,可以快捷方便地浏览文档或页。 按钮 描述 添加文档 - 输入一个新的文档。在使用数据查看器的任何时候,点击此按钮来得到一个空白的文档。 删除文档 - 删除一个现有的文档。 应用更改 - 应用已做的更改。 放弃更改 - 移除当前记录的全部编辑。 刷新 - 刷新数据。 停止 - 当从服务器加载大量数据时,停止加载。 第一页 - 移动到第一页。 上一页 - 移动到上一页。

  • 使用数据查看器的“导航栏”按钮,可以快捷方便地浏览记录或页。 按钮 描述 添加记录 - 输入一条新的记录。在使用数据查看器的任何时候,点击此按钮来得到一条空白的记录。 删除记录 - 删除一条现有的记录。 应用更改 - 应用已做的更改。 放弃更改 - 移除当前记录的全部编辑。 刷新 - 刷新数据。 停止 - 当从服务器加载大量数据时,停止加载。 第一页 - 移动到第一页。 上一页 - 移动到上一页。

  • 使用数据查看器的“导航栏”按钮,可以快捷方便地浏览文档或页。 按钮 描述 添加文档 - 输入一个新的文档。在使用数据查看器的任何时候,点击此按钮来得到一个空白的文档。 删除文档 - 删除一个现有的文档。 应用更改 - 应用已做的更改。 放弃更改 - 移除当前记录的全部编辑。 刷新 - 刷新数据。 停止 - 当从服务器加载大量数据时,停止加载。 第一页 - 移动到第一页。 上一页 - 移动到上一页。

  • 使用数据查看器的“导航栏”按钮,可以快捷方便地浏览记录或页。 按钮 描述 添加记录 - 输入一条新的记录。在使用表查看器的任何时候,点击此按钮来得到一条空白的记录。 删除记录 - 删除一个现有的记录。 应用更改 - 应用已做的更改。 放弃更改 - 移除当前记录的全部编辑。 刷新 - 刷新数据。 停止 - 当从服务器加载大量数据时,停止加载。 第一页 - 移动到第一页。 上一页 - 移动到上一页。

  • 使用数据查看器的“导航栏”按钮,可以快捷方便地浏览文档或页。 按钮 描述 添加文档 - 输入一个新的文档。在使用数据查看器的任何时候,点击此按钮来得到一个空白的文档。 删除文档 - 删除一个现有的文档。 应用更改 - 应用已做的更改。 放弃更改 - 移除当前记录的全部编辑。 刷新 - 刷新数据。 停止 - 当从服务器加载大量数据时,停止加载。 第一页 - 移动到第一页。 上一页 - 移动到上一页。