Reputation: 1478
Im trying to pass a list of Composables, in this case Columns, as a parameter to later populate a view, for that I'm adding the parameter List<@Composable (ColumnScope.() -> Unit)> on a composable function and populating a List with simple Columns.
The problem I'm having is that the Columns generate a Type mismatch
Required:
List<ColumnScope.() → Unit>
Found:
List<Unit>
Is there a way to achieve this? Here I'll provide my code.
@Composable
fun LotsOfColumns() {
ColumnListSample(
myColumns = listOf(
Column {},
Column {}
)
)
}
@Composable
fun ColumnListSample(
myColumns: List<@Composable (ColumnScope.() -> Unit)>,
modifier: Modifier = Modifier
) {}
Upvotes: 3
Views: 3960
Reputation: 4441
This is how it's declared:
@Composable
fun SettingsRow(
modifier: Modifier? = null,
horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
verticalAlignment: Alignment.Vertical = Alignment.CenterVertically,
children: List<@Composable RowScope.() -> Unit>,
onClick: () -> Unit
)
This is how composable list passed as parameter:
SettingsRow(
children = listOf(
{ Icon(Icons.Rounded.Done, contentDescription = "Done") },
{
Row(modifier = Modifier.weight(1.0f)) {
Text(text = config.name)
}
}
)
)
This is how the children
is used in SettingsScreen
composable.
Row(modifier = Modifier.weight(1.0f)) {
children.map { it ->
it()
}
}
Upvotes: 2
Reputation: 67293
I do this by wrapping @Composable functions inside a data class or a class then pass that class with a List
data class TutorialSectionModel(
val title: String,
val action: @Composable (() -> Unit)? = null,
val description: String,
val tags: List<String> = listOf(),
val tagColor: Color = DefaultListColor,
var expanded: Boolean = false
)
And create a list of that class that contains that Composables and i pass them to my LazyColumn.
val tutorialList = mutableListOf<List<TutorialSectionModel>>()
Use it with LazyColumn
LazyColumn(
content = {
items(
items = tutorialList,
key = {
it.title
}
) { item: TutorialSectionModel ->
var isExpanded by remember(key1 = item.title) { mutableStateOf(item.expanded) }
TutorialSectionCard(
model = item,
onClick = {
navigateToTutorial(item.title)
},
onExpandClicked = {
item.expanded = !item.expanded
isExpanded = item.expanded
},
expanded = isExpanded
)
}
}
You can pass your @Composable (ColumnScope.() -> Unit
to a class you created same way.
Maybe not in your question scope, the way wrapping inside a class helps passing this list to a ViewModel and i use this action or Composables as navigation target too instead of writing tens of composable navigation routes.
// Set navigation route as title of tutorial card
// and invoke @Composable inside lambda of this card.
mainViewModel.tutorialList.forEach { list ->
list.forEach { model ->
composable(route = model.title) { navBackEntryStack ->
// This column is used for setting navigation padding since
// NavHost only has statusBarsPadding to let main screen list have
// inset at the bottom with WindowInsetsSides.Bottom
Column(Modifier.navigationBarsPadding()) {
// 🔥 These are @Composable screens such as Tutorial2_1Screen()
model.action?.invoke()
}
}
}
}
Upvotes: 4
Reputation: 101
@Composable fun LotsOfColumns() {
ColumnListSample(
myColumns = listOf(
{ Column {} },
{ Column {} }
)
)
}
Upvotes: 4