Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 719
Charles Woodson Avatar asked May 25 '21 00:05

Charles Woodson


People also ask

What is lazy column in jetpack compose?

Then, we will talk about lazy column, which is the recyclerview equivalent in jetpack compose. We will create a simple recycler view using lazy column, and, we will learn how to implement the click listener for list items.

How does the lazycolumn list work?

As currently implemented, the LazyColumn list is populated directly from an array of string values. The goal is now to group those items by manufacturer, with each group preceded in the list by a sticky header displaying the manufacturer’s name.

How to set current tab of text in lazycolumn?

LazyColumn ( ... modifier = Modifier.nestedScroll (nestedScrollConnection) ) { items (...) { Text ("Your text...") } } 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.

What is the latest version of jetpack compose?

At the time of writing, the latest version of Jetpack Compose is 1.1.0-rc02. Using the BringIntoViewRequester requires you to opt into the ExperimentalFoundationApi which is subject to change.


3 Answers

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(),
                        )
                    }
                }
            }
        }
    }
}
like image 182
Felix Schütz Avatar answered Oct 19 '22 21:10

Felix Schütz


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...")
    }
}
like image 8
Senocico Stelian Avatar answered Oct 19 '22 22:10

Senocico Stelian


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.

like image 3
Ryan M Avatar answered Oct 19 '22 21:10

Ryan M