Charles Woodson
Charles Woodson

Reputation: 858

Jetpack Compose LazyColumn Scroll Listener

I want to programmatically change which tab is selected as the user scrolls past each "see more" item in the list below. How would I best accomplish this?

enter image description here

Upvotes: 27

Views: 31114

Answers (3)

Senocico Stelian
Senocico Stelian

Reputation: 1687

Just create a NestedScrollConnection and assign it to parent view nestedScroll modifier:

val nestedScrollConnection = remember {
    object : NestedScrollConnection {
        override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset {
            val delta = available.y
            // called when you scroll the content
            return Offset.Zero
        }
    }
}

Assign it to LazyColumn or to its parent composed view:

Modifier.nestedScroll(nestedScrollConnection)

Exemple:

LazyColumn(
    ...
    modifier = Modifier.nestedScroll(nestedScrollConnection)
) {
    items(...) {
       Text("Your text...")
    }
}

Upvotes: 29

Felix Schütz
Felix Schütz

Reputation: 1377

As Ryan M writes, you can use LazyListState.firstVisibleItemIndex. The magic of Compose is that you can just use it in an if statement and Compose will do the work. Look at the following example, which displays a different text based on the first visible item. Similarly, you can select a different tab based on the first visible item.

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setContent {
            val listState = rememberLazyListState()

            Column {
                Text(if (listState.firstVisibleItemIndex < 100) "< 100" else ">= 100")
                LazyColumn(state = listState) {
                    items(1000) {
                        Text(
                            text = "$it",
                            modifier = Modifier.fillMaxWidth(),
                        )
                    }
                }
            }
        }
    }
}

Upvotes: 19

Ryan M
Ryan M

Reputation: 20119

You can use the LazyListState.firstVisibleItemIndex property (obtained via rememberLazyListState and set as the state parameter to LazyColumn) and set the current tab based on that.

Reading that property is considered a model read in Compose, so it will trigger a recomposition whenever the first visible item changes.

If you instead want to do something more complex based on more than just the first visible item, you can use LazyListState.layoutInfo to get information about all visible items and their locations, rather than just the first.

Upvotes: 9

Related Questions