Как изменить действие кнопки Scaffold Floating Action Button на разных экранах. Jetpack Compose

Как я могу изменить действие FAB (onClick{}) в зависимости от текущего экрана с помощью Scaffold.

                  Scaffold(
                floatingActionButton = {
                    FloatingActionButton(onClick = { 
                        //Different actions here depending on current screen
                    }) { }
                }
            ) {
                NavHost(
                    navController = navController,
                    startDestination = "route1"
                ) {
                    composable(
                        route = "route1"
                    ) {
                        ScreenOne()
                    }

                    composable(
                        route = "route2"
                    ) {
                        ScreenTwo()
                    }
                }
            }

Например, с помощью ScreenOne () я хочу добавить некоторые объекты в базу данных, а с помощью ScreenTwo () я хочу сохранить отредактированный объект. И все это с использованием той же FAB, которая используется в Scaffold.

3 ответа

Я решил проблему так.

  1. Определите изменяемое состояние функции обратного вызова. Это где-то за пределами вашего Scaffold (в моем случае в моей компонуемой навигации):
      val floatingActionButtonFunction = remember { mutableStateOf({})}
  1. Предоставьте функцию обратного вызова в составном объекте, содержащем Scaffold, и вызывайте ее при нажатии кнопки floatActionButton:
      @Composable
fun LayoutScreen(
    appState: AppState,
    onFloatingActionButtonClick: (() -> Unit)? = null,
    content: @Composable () -> Unit,
) {
    Scaffold(
        floatingActionButtonPosition = FabPosition.End,
        floatingActionButton = {
            FloatingActionButton(onClick = {
                if (onFloatingActionButtonClick != null) {
                    onFloatingActionButtonClick()
                }
            }) {
                Icon(imageVector = Icons.Default.Add, contentDescription = "fab icon")
            }
        },
        // rest of your Scaffold
    )
}
  1. Настройте навигацию, предоставив функцию для фактического компонуемого представления:
      composable(route = ScreenNavigation.AccountScreeen.route) {
            LayoutScreen(appState = appState, onFloatingActionButtonClick = {floatingActionButtonFunction.value()}) {
                AccountScreen(appState, floatingActionButtonFunction)
            }
        }
  1. На ваш взгляд (фактически показанная составная часть) перезапишите функцию:
      @Composable
fun AccountScreen(appState: AppState, floatingActionButtonAction: MutableState<() -> Unit>) {
floatingActionButtonAction.value = {
            Store.instance.dispatch(NavigationActions.SetNavigation(
                Navigation(ScreenNavigation.PaymentScreen.route)))
        }
}

Вы можете наблюдать текущий маршрут NavController и выполните действие соответственно.

      // When you navigate to another screen, this value is updated.
val currentRoute = navController
    .currentBackStackEntryFlow
    .collectAsState(initial = navController.currentBackStackEntry)

Scaffold(
    floatingActionButton = {
        FloatingActionButton(
            onClick = {
                when (currentRoute.value?.destination?.route) {
                    "screen1" -> { /* Action for Screen 1 */ }
                    "screen2" -> { /* Action for Screen 2 */ }
                    // ...
                }
            }
        ) {
            Icon(Icons.Default.Add, contentDescription = null)
        }
    }
) {
    NavHost(navController = navController, startDestination = "screen1") {
        composable("screen1") { Screen1() }
        composable("screen2") { Screen2() }
    }
}

Если вы используете Navigation, вы можете получить navController от rememberNavController() а затем используйте это, чтобы getCurrentBackStackEntry().destination, применяя условные выражения в onClick заблокировать и установить действие соответствующим образом

Другие вопросы по тегам