Как изменить действие кнопки 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 ответа
Я решил проблему так.
- Определите изменяемое состояние функции обратного вызова. Это где-то за пределами вашего Scaffold (в моем случае в моей компонуемой навигации):
val floatingActionButtonFunction = remember { mutableStateOf({})}
- Предоставьте функцию обратного вызова в составном объекте, содержащем 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
)
}
- Настройте навигацию, предоставив функцию для фактического компонуемого представления:
composable(route = ScreenNavigation.AccountScreeen.route) {
LayoutScreen(appState = appState, onFloatingActionButtonClick = {floatingActionButtonFunction.value()}) {
AccountScreen(appState, floatingActionButtonFunction)
}
}
- На ваш взгляд (фактически показанная составная часть) перезапишите функцию:
@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
заблокировать и установить действие соответствующим образом