如何从子可组合项控制脚手架的 FloatingActionButton onClick?

Ham*_* XD 4 android-navigation android-jetpack-compose jetpack-compose-navigation

是否可以从可组合的屏幕(也在 aFloatingActionButton内部)设置 aonClick内部的值?在我的示例中,我希望能够更改 FAB 的 onClick 以根据屏幕可组合项内的值 ( ) 进行一些计算,而不将该值提升到该值所在的可组合项( )。ScaffoldNavHostScaffoldnameScaffoldMyActivity()

@Composable
fun MyActivity() {
    val navController = rememberNavController()

    Scaffold(
        floatingActionButton = {
            FloatingActionButton(onClick = { /* set this lambda from Screen1 */ }) { ... }
        }
    ) { paddingValues ->
        NavHost(
            navController = navController,
            startDestination = Screen.Screen1.route,
            modifier = Modifier.padding(paddingValues)
        ) {
            composable(route = Screen.Screen1.route) {
                Screen1()
            }
            ...
        }
    }
}

@Composable
fun Screen1() {
    var name by remember { mutableStateOf(TextFieldValue("") }

    TextField(value = name, onValueChange = { name = it })

    // Set FAB onClick to do some calculations on name without hoisting the variable
    setFabOnClick { name.calculate() }
}
Run Code Online (Sandbox Code Playgroud)

Phi*_*hov 8

我不知道为什么你不想把这个值放在顶视图中。如果您在示例中这样做,则更新文本不会导致 的重新组合MyActivity,只是Screen1- Compose 足够智能,可以做到这一点。

在任何情况下,您都可以创建一个可变状态来存储处理程序并在Screen1. 我使用它是LaunchedEffect因为更新状态是一个副作用,不应该直接从视图构造函数中完成,也不需要在每次重组时都这样做。

@Composable
fun Screen1(
    setFabOnClick: (() -> Unit) -> Unit,
) {
    var name by remember { mutableStateOf(TextFieldValue("")) }

    TextField(value = name, onValueChange = {name = it})

    LaunchedEffect(Unit) {
        setFabOnClick { println("$name") }
    }
}

@Composable
fun MyActivity() {
    val navController = rememberNavController()
    val (fabOnClick, setFabOnClick) = remember { mutableStateOf<(() -> Unit)?>(null) }

    Scaffold(
        floatingActionButton = {
            FloatingActionButton(onClick = {
                fabOnClick?.invoke()
            }) {
                Icon(Icons.Default.ReportProblem, null)
            }
        }
    ) { paddingValues ->
        NavHost(
            navController = navController,
            startDestination = Screen.Screen1.route,
            modifier = Modifier.padding(paddingValues)
        ) {
            composable(route = Screen.Screen1.route) {
                Screen1(setFabOnClick = setFabOnClick)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @stefan.at.wpf 在这里不使用 `LaunchedEffect` 是违反 [Compose 原则](https://developer.android.com/jetpack/compose/mental-model) - 可组合项应该没有副作用,以获得更好的性能。原因之一是,如果没有“LaunchedEffect”,每次更新“name”时,它也会重新组合“MyActivity”,但最好始终使您的可组合项没有副作用,即使在特定情况下看起来没问题只是打电话 (2认同)