HI, is it possible to synchronize scrolling for mu...
# compose
g
HI, is it possible to synchronize scrolling for multiple LazyColumns? I tried to share rememberLazyListState but this has strange behavior
w
What strange behavior did you hit? I recently did this with multiple rows and it seems to work for me.
Ah, wait, my rows weren't lazy. I think that might the problem, because the lazy layouts don't use absolute offsets.
☝️ 1
✔️ 1
They target item positions, because they don't know the total range since it's lazy.
g
sometimes one columnt would scroll slighly then it would scroll first column
w
What's the UI you're trying to achieve? You can get close to parallel lazy columns with a LazyStaggeredVerticalGrid. Although you'd need custom logic to sort your items into spans instead of sequentially, since LSVG will layout left to right first.
g
well, the layout is quite complex and probably will take me a lot of messages and pics to explain
s
rememberLazyListState()
has a lot of internal logic which manages visible items, fetching logic, as well as the scroll state. I wouldn't expect it to just work compared to something simpler, like
rememberScrollState()
but
LazyListState
inherits from
ScrollableState
, so maybe something like having a "parent" and "child" scrolling layout would be possible
w
If you want to approximate it without major changes, maybe you can intercept scrolling on any column and call
scrollBy(delta)
on all of the columns.
g
in short I want something like stickyHeader on left side and also on the bottom
Currently I have LazyRow
okay, 1 min, at least I will give you a pic
So Im making something like a chart. The change is that there will be more than one user and this chart will need to be scrolled top and bottom. it already scrolls right and left. So that means I have to add 2 StickyHeader one on left for users and one on bottom for timeline. but StickyHeader only works at top 😕
one idea I have is to have scrollable items in the row, but timeline will be static
and users will appear on separate list
w
It sounds like your timeline doesn't have to be part of the lazy layout at all. Just making it static but sync based on some listener on the scroll state seems fine. The same for the left side, too.
👍 1
g
So if someone wants 2 LazyColumn's scroll being synchronised, here it is
Copy code
@Composable
fun SynchronizedScrollLazyColumns() {
    val leftListState = rememberLazyListState()
    val rightListState = rememberLazyListState()
    val coroutineScope = rememberCoroutineScope()

    fun syncScroll(leading: LazyListState, following: LazyListState) {
        coroutineScope.launch {
            val scrollPosition = leading.firstVisibleItemScrollOffset
            following.scrollToItem(
                index = leading.firstVisibleItemIndex,
                scrollOffset = scrollPosition
            )
        }
    }

    // Observe scroll changes in the LEFT column
    LaunchedEffect(leftListState.firstVisibleItemIndex, leftListState.firstVisibleItemScrollOffset) {
        syncScroll(leftListState, rightListState)
    }

    // Observe scroll changes in the RIGHT column
    LaunchedEffect(rightListState.firstVisibleItemIndex, rightListState.firstVisibleItemScrollOffset) {
        syncScroll(rightListState, leftListState)
    }
    Row(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        // Left Column (Leading Column)
        LazyColumn(
            modifier = Modifier
                .weight(1f),
            state = leftListState
        ) {
            items(20) { index ->
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(4.dp),
                    elevation = CardDefaults.cardElevation(4.dp)
                ) {
                    Text(
                        text = "Left Item $index",
                        modifier = Modifier.padding(16.dp)
                    )
                }
            }
        }

        Spacer(modifier = Modifier.width(8.dp))

        // Right Column (Following Column)
        LazyColumn(
            modifier = Modifier
                .weight(1f),
            state = rightListState
        ) {
            items(20) { index ->
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(4.dp),
                    elevation = CardDefaults.cardElevation(4.dp)
                ) {
                    Text(
                        text = "Right Item $index",
                        modifier = Modifier.padding(16.dp)
                    )
                }
            }
        }
    }
}
🙌 1