Home > Software design >  How to pass a Composable to another Composable as its parameter and display/run it in Jetpack Compos
How to pass a Composable to another Composable as its parameter and display/run it in Jetpack Compos

Time:12-04

I have this drawer I learned to make on youtube

SwipeScreen enter image description here

I want to add the drawer to my app which has multiple screens and some of them don't need the drawer so I implemented navigation with screens , and some of the screens need to also have the drawer ontop of them wrap them.

this is the code of the drawer


val scaffoldState = rememberScaffoldState()
                val scope = rememberCoroutineScope()
                Scaffold(
                    drawerGesturesEnabled = scaffoldState.drawerState.isOpen,
                    scaffoldState = scaffoldState, topBar = {
                    AppBar(onNavigationIconClick = {
                        scope.launch {
                            scaffoldState.drawerState.open()
                        }

                    })
                }, drawerContent = {
                    DrawerHeader()
                    DrawerBody(items = listOf(
                        MenuItem(
                            id = "home",
                            title = "Home",
                            contentDescription = "Go to home screen",
                            icon = Icons.Default.Home
                        ),
                        MenuItem(
                            id = "settings",
                            title = "Settings",
                            contentDescription = "Go to Settings screen",
                            icon = Icons.Default.Settings
                        ),
                        MenuItem(
                            id = "help",
                            title = "Help",
                            contentDescription = "Go to help screen",
                            icon = Icons.Default.Info
                        ),
                    ), onItemClick = {
                        println("Clicked on ${it.title}")

                        when (it.id) {
                            "home" -> {
                                println("Clicked on ${it.title}")
                            }
                            "settings" -> {
                                println("Clicked on ${it.title}")
                            }
                            "help" -> {
                                println("Clicked on ${it.title}")
                            }
                        }
                    })

                }) {

                    Text(text = "Hello World")

                }

the Text = Hellow world is where I want to pass my parameter of the screen which I don't know how to do it. I want to add a parameter that takes a composable function and runs it inside

and I followed this navigation video on how to navigate in kotlin

enter image description here

CodePudding user response:

I can't compile your code and I'm not sure if this will solve your issue, but based on this

… I want to add a parameter that takes a composable function and runs it inside

You can use this as a reference. Consider this composable that takes any composable and runs it inside

@Composable
fun AnyComposable(
    anyComposable: @Composable () -> Unit
) {
    anyComposable()
}

And another composable that uses the composable above and passes any other composable to it like this

@Composable
fun MyScreen() {

    // big red Box composable
    val composable1 = @Composable {
        Box (
            modifier = Modifier
                .size(200.dp)
                .background(Color.Red)
        )
    }

    // small blue Box composable
    val composable2 = @Composable {
        Box(
            modifier = Modifier
                .size(80.dp)
                .background(Color.Blue)
        )
    }

    // small green rectangular Box composable
    val composable3 = @Composable {
        Box(
            modifier = Modifier
                .size(width = 100.dp, height = 30.dp)
                .background(Color.Green)
        )
    }

    var dynamicComposable by remember { mutableStateOf<@Composable () -> Unit> (@Composable { composable1() }) }

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
            Button(onClick = {
                dynamicComposable = composable1
            }) {
                Text("Comp 1")
            }

            Button(onClick = {
                dynamicComposable = composable2
            }) {
                Text("Comp 2")
            }

            Button(onClick = {
                dynamicComposable = composable3
            }) {
                Text("Comp 3")
            }
        }

        AnyComposable {
            dynamicComposable()
        }
    }
}

and the output:

enter image description here

CodePudding user response:

Or if in case the receiving composable has, lets say a Column, and you want to set-up the argument composables with Alignment beforehand, you can consider this one.

Same composable reciever that accepts any composables but the expected layout is Column.

@Composable
fun AnyComposable(
    anyComposable: @Composable () -> Unit
) {
    Column(
        modifier = Modifier.fillMaxSize()
    ) {
        anyComposable()
    }
}
@Composable
fun MyScreen() {

    // big red box at Start of Column
    val composable1 : @Composable ColumnScope.() -> Unit = @Composable {
        Box (
            modifier = Modifier
                .align(Alignment.Start)
                .size(200.dp)
                .background(Color.Red)
        )
    }

    // small blue box at Center of Column
    val composable2 : @Composable ColumnScope.() -> Unit = @Composable {
        Box(
            modifier = Modifier
                .align(Alignment.CenterHorizontally)
                .size(80.dp)
                .background(Color.Blue)
        )
    }

    // small green rectangle at End of Colummn
    val composable3 : @Composable ColumnScope.() -> Unit = @Composable {
        Box(
            modifier = Modifier
                .align(Alignment.End)
                .size(width = 100.dp, height = 30.dp)
                .background(Color.Green)
        )
    }

    var dynamicComposable by remember { mutableStateOf<@Composable ColumnScope.() -> Unit> (@Composable { composable1() }) }

    Column(
        modifier = Modifier.fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {

        Row(
            modifier = Modifier.fillMaxWidth(),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.SpaceBetween
        ) {
            Button(onClick = {
                dynamicComposable = composable1
            }) {
                Text("Comp 1")
            }

            Button(onClick = {
                dynamicComposable = composable2
            }) {
                Text("Comp 2")
            }

            Button(onClick = {
                dynamicComposable = composable3
            }) {
                Text("Comp 3")
            }
        }

        AnyComposable {
            dynamicComposable()
        }
    }
}

Output:

enter image description here

  • Related