compose-multiplatform
compose-multiplatform copied to clipboard
LazyColumn stickyHeader breaks in very specific edge case
This is the best I could reduce it to. If you can't reproducer, try making a bigger/maximised window.
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.FilterList
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowSize
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
import kotlinx.coroutines.flow.MutableSharedFlow
@OptIn(ExperimentalComposeUiApi::class)
fun main() {
application {
val windowState = rememberWindowState(size = WindowSize(1280.dp, 720.dp))
Window(windowState, title = "Sticky Header Issue!!!") {
MaterialTheme {
Reproducer()
}
}
}
}
class Model(
val list1: List<String> = emptyList(),
val list2: List<String> = emptyList(),
val list3: List<String> = emptyList(),
)
@Composable
fun Reproducer() {
val model = remember { MutableSharedFlow<Model>(extraBufferCapacity = 1) }
Column(Modifier.fillMaxWidth(0.3f)) {
Row(Modifier.fillMaxWidth(), Arrangement.spacedBy(8.dp), Alignment.CenterVertically) {
Spacer(Modifier.width(5.dp))
OutlinedTextField(
value = "roomFilter",
onValueChange = { },
modifier = Modifier.weight(1f),
placeholder = { Text("Filter...") },
leadingIcon = { Icon(Icons.Filled.FilterList, null) }
)
}
Column {
Button(
onClick = {
val stuff = (1..20).map { "Item $it" }
val res = model.tryEmit(Model(stuff, stuff, stuff))
check(res)
}
) {
Text("Show Bug!")
}
val modelProxy = model.collectAsState(Model()).value
// val modelProxy by model.collectAsState(Model()) // This works?!?!?!
LazyColumn {
fun section(header: String, list: List<String>) {
@OptIn(ExperimentalFoundationApi::class)
stickyHeader { Text(header, style = MaterialTheme.typography.subtitle1) }
items(list) { Text(it) }
}
section("Header1", modelProxy.list1)
section("Header2", modelProxy.list2)
section("Header3", modelProxy.list3)
section("Header4", modelProxy.list3)
}
}
}
}
Before clicking the "Show Bug!" button you should see this.

After clicking the "Show Bug!" button you should see this.

I expected to see this instead. (You can see this if you use the other modelProxy declaration).

I'm not 100% sure why val modelProxy = model.collectAsState(Model()).value breaks but val modelProxy by model.collectAsState(Model()) works.
I'm on Arch Linux (i3 & X11) and Compose-Desktop 0.4.0.
Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.