androidkotlinandroid-jetpack-composelazylist

How to make the first and last item non-scrollable, but only the middle section?


I need to show a list of numbers in a LazyRow (I picked lazyrow as there can be like 200 numbers). The first number and the last number should be always visible on the left and right side. The rest of the numbers need to be able to horizontally scroll. How can I achieve this?

See attached image: black border sticky/fixed, grey border scrollable.

I tried putting LazyRow inside a Row, but it does not work unless I predefine the LazyRow's item width (which I don't know as the numbers will be dynamic, could be 5 digit or more).

I also tried using stickyHeader but it does not allow me to use that for both left and right side, especially if there are only 1 or 2 numbers between the first and last.


Solution

  • Using a LazyRow inside a Row is a good approach, the only thing that is missing is the weight modifier on the LazyRow.

    That modifier distributes the space among its siblings according to the given weight. All siblings that do not have a weight modifier take up as much space as needed. If only the LazyRow has a weight modifier that means that the other elements of the surrounding Row are measured first and the LazyRow will then take up all the remaining space. This way the first and the last element will always have enough space left so they can be displayed.

    You could use something like this:

    Row {
        val first = list.firstOrNull() ?: return@Row
        MyItem(first)
    
        val middleList = list.subList(1, list.lastIndex)
        if (middleList.isNotEmpty())
            LazyRow(
                modifier = Modifier.weight(1f),
            ) {
                items(middleList) { MyItem(it) }
            }
    
        val last = list.subList(1, list.size).lastOrNull() ?: return@Row
        MyItem(last)
    }
    

    list is the list of items to display and MyItem is the composable to display such an item.