Modify sample code from Jetpack Compose Paging Sample.
Modify MemberRepository
to generate age in sequence.
class MemberRepository(val totalCount: Int, val pageSize: Int) { suspend fun getMembers(page: Int): List<Member> { val random = Random(page) val startIndex = (page - 1) * pageSize + 1 var endIndex = startIndex + pageSize - 1 if (endIndex > totalCount) { endIndex = totalCount } return (startIndex..endIndex).map { index -> // Member(name = "Member #${index}", age = random.nextInt(1, 99)) Member(name = "Member #${index}", age = index) } }}
Sample using Sticky Header
@ExperimentalFoundationApi@Composablefun MemberScreen(viewModel: MemberViewModel = viewModel()) { val lazyMembers = viewModel.membersFlow.collectAsLazyPagingItems() LazyColumn { val itemCount = lazyMembers.itemCount var lastAgeGroup: Int? = null for (index in 0 until itemCount) { val nextMember = lazyMembers.peek(index) if (nextMember != null) { val age = nextMember.age // create a header for every 10y of age if (lastAgeGroup == null || age > lastAgeGroup) { lastAgeGroup = (lastAgeGroup ?: 0) + 10 val ageGroup = lastAgeGroup stickyHeader(key = ageGroup) { Text("<= $ageGroup") } } } val member = lazyMembers[index] if (member != null) { item(key = member.name) { Text("${member.name}, age=${member.age}") } } } }}
Sample using Text
as header.
@ExperimentalFoundationApi@Composablefun MemberScreen(viewModel: MemberViewModel = viewModel()) { val lazyMembers = viewModel.membersFlow.collectAsLazyPagingItems() LazyColumn { val itemCount = lazyMembers.itemCount var lastAgeGroup: Int? = null for (index in 0 until itemCount) { val nextMember = lazyMembers.peek(index) var ageGroup: Int? = null if (nextMember != null) { val age = nextMember.age if (lastAgeGroup == null || age > lastAgeGroup) { lastAgeGroup = (lastAgeGroup ?: 0) + 10 ageGroup = lastAgeGroup } } val member = lazyMembers[index] if (member != null) { item(key = member.name) { if (ageGroup != null) { Text("< $ageGroup") } Text("${member.name}, age=${member.age}") } } } }}
Alternatively, you can also group data together before render them.
@ExperimentalFoundationApi@Composablefun MemberScreen(viewModel: MemberViewModel = viewModel()) { val lazyMembers = viewModel.membersFlow.collectAsLazyPagingItems() val memberGroup = mutableMapOf<String, MutableList<Int>>() val itemCount = lazyMembers.itemCount var lastAgeGroup: Int? = null // to fill up memberGroup, will not trigger any render for (index in 0 until itemCount) { val nextMember = lazyMembers.peek(index) var ageGroup: Int? = null if (nextMember != null) { val age = nextMember.age if (lastAgeGroup == null || age > lastAgeGroup) { lastAgeGroup = (lastAgeGroup ?: 0) + 10 ageGroup = lastAgeGroup memberGroup[lastAgeGroup] = mutableListOf() } memberGroup[lastAgeGroup]?.add(index) } } // actual render for ((ageGroup, memberIndexes) in memberGroup) { stickyHeader(key = ageGroup) { Text("< $ageGroup") } // you can group render into single item(...), or use individual item(...) for each item(key = "$ageGroup-members") { for (index in memberIndexes) { // this will trigger pageload val member = lazyMembers[index] Column { Text("${member.name}, age=${member.age}") } } } }}