https://kotlinlang.org logo
#compose
Title
# compose
m

ms

07/31/2021, 3:14 AM
I have a Settings screen which shows list of settings item and under each item there will be more settings which shows/hides on parent click but Compose doesn't allow to use
NestedScrollable
inside
Column
or
LazyColumn
code in 🧵
Copy code
LazyColumn(
    modifier = Modifier.fillMaxSize(),
    verticalArrangement = Arrangement.Center,
) {
    items(count = 17) { index ->
        ShowContent(text = "Index $index")
    }
}


@ExperimentalFoundationApi
@OptIn(ExperimentalAnimationApi::class)
@Composable
private fun ShowContent(text: String) {
    var showContent by remember { mutableStateOf(false) }
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .clickable { showContent = !showContent }
            .padding(horizontal = 12.dp, vertical = 8.dp),
    ) {
        Column {
            Text(
                text = text,
                style = TextStyle(color = MaterialTheme.colors.onBackground),
            )
            AnimatedVisibility(
                visible = showContent,
                modifier = Modifier.padding(vertical = 8.dp),
            ) {
                LazyVerticalGrid(
                    cells = GridCells.Fixed(2),
                    modifier = Modifier.wrapContentHeight(),
                ) {
                    items(count = 4) { index ->
                        Text(
                            text = "Grid $index",
                            style = TextStyle(color = MaterialTheme.colors.onBackground),
                        )
                    }
                }
            }
        }
    }
}
c

Colton Idle

07/31/2021, 3:26 AM
I would make the top most column a lazy column filled with a list of Settings all in a collapsed state, and then inside of Settings composable you pass in the sub-settings, and on click of settings you use AnimatedContent to expand and show the subsettings.
Copy code
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            SettingsTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    val list = listOf(
                        SettingsWithSubSettings(
                            "Setting 1",
                            listOf("SubSetting 1", "SubSetting 2", "SubSetting 3")
                        ),
                        SettingsWithSubSettings(
                            "Setting 2",
                            listOf("SubSetting 1", "SubSetting 2", "SubSetting 3")
                        ),
                        SettingsWithSubSettings(
                            "Setting 3",
                            listOf("SubSetting 1", "SubSetting 2", "SubSetting 3")
                        ),
                        SettingsWithSubSettings(
                            "Setting 4",
                            listOf("SubSetting 1", "SubSetting 2", "SubSetting 3")
                        ),
                    )
                    LazyColumn(Modifier.fillMaxSize()) {
                        items(list) {
                            Setting(settingName = it.settingName, subSettings = it.subSettingList)
                        }
                    }
                }
            }
        }
    }
}

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun Setting(settingName: String, subSettings: List<String>) {
    var visible by remember { mutableStateOf(false) }
    Text(text = settingName, modifier = Modifier.clickable { visible = !visible })
    AnimatedVisibility(visible = visible) {
        Column() {
            subSettings.forEach {
                Text(text = it)
            }
        }
    }
}

data class SettingsWithSubSettings(val settingName: String, val subSettingList: List<String>)
Produces an output like this
I think Andrey Kulikov [G] has basically said that you can't have an inifinite height container inside of an inifinite height container. LazyColumn is infinitely height, and so I don't think it can hold other scrollable containers? I'm no expert though. Maybe he can chime in.
a

Abhishek Dewan

07/31/2021, 3:44 AM
yea it won't work that ways. You might want to have a lazycolumn with composable that can toggle between expanded and non expanded states.
m

ms

07/31/2021, 3:47 AM
yes, it makes no sense to have an infinite height column inside an infinite one but the problem is
LazyVerticalGrid
takes infinite height
maybe I'll try to layout manually instead of using LazyVerticalGrid that might work
a

Abhishek Dewan

07/31/2021, 3:57 AM
i’ve found lazy vertical grid too limiting for my use cases and also too unpredictable
so I’ve preferred to handroll mine
a

Andrey Kulikov

07/31/2021, 12:35 PM
@Abhishek Dewan we are planning to finialize and stabilze the api shape of LazyVerticalGrid for 1.1 so any feedback about missed functionality will be useful! please file a bug with your input