简体   繁体   English

Jetpack Compose 中带有分页库的粘性标头

[英]Sticky headers with paging library in Jetpack Compose

I'm currently playing around with the new Jetpack compose UI toolkit and I like it a lot.我目前正在使用新的 Jetpack compose UI 工具包,我非常喜欢它。 One thing I could not figure out is how to use stickyHeaders in a LazyColumn which is populated by the paging library.我想不通的一件事是如何在分页库填充的LazyColumn中使用stickyHeaders The non-paging example from the documentation is: 文档中的非分页示例是:

val grouped = contacts.groupBy { it.firstName[0] }

fun ContactsList(grouped: Map<Char, List<Contact>>) {
    LazyColumn {
        grouped.forEach { (initial, contactsForInitial) ->
            stickyHeader {
                CharacterHeader(initial)
            }

            items(contactsForInitial) { contact ->
                ContactListItem(contact)
            }
        }
    }
}

Since I'm using the paging library I cannot use the groupedBy so I tried to use the insertSeparators function on PagingData and insert/create the headers myself like this (please ignore the legacy Date code, it's just for testing):由于我使用的是分页库,因此我无法使用groupedBy ,因此我尝试在 PagingData 上使用insertSeparators PagingData并自己插入/创建标题(请忽略旧Date代码,它仅用于测试):

// On my flow
.insertSeparators { before, after ->
        when {
            before == null -> ListItem.HeaderItem(after?.workout?.time ?: 0)
            after == null -> ListItem.HeaderItem(before.workout.time)
            (Date(before.workout.time).day != Date(after.workout.time).day) ->
                ListItem.HeaderItem(before.workout.time)
            // Return null to avoid adding a separator between two items.
            else -> null
        }
    }

// In my composeable
LazyColumn {
    items(workoutItems) {
        when(it) {
            is ListItem.HeaderItem -> this@LazyColumn.stickyHeader { Header(it) }
            is ListItem.SongItem -> WorkoutItem(it)
        }
    }
}

But this produces a list of all my items and the header items are appended at the end.但这会生成我所有项目的列表,并且 header 项目附加在末尾。 Any ideas what is the right way to use the stickyHeader function when using the paging library?任何想法在使用分页库时使用stickyHeader function 的正确方法是什么?

I got it work by looking into the source code of the items function: You must not call stickyHeader within the items function.我通过查看items function 的源代码得到了它:你不能在items function 中调用stickyHeader No need to modify the PagingData flow at all.根本不需要修改 PagingData 流。 Just use peek to get the next item without trigering a reload and then layout it:只需使用 peek 获取下一个项目而不触发重新加载,然后对其进行布局:

LazyColumn {
    val itemCount = workoutItems.itemCount
    var lastWorkout: Workout? = null

    for(index in 0 until itemCount) {
        val workout = workoutItems.peek(index)

        if(lastWorkout ?.time != workout?.time) stickyHeader { Header(workout) }
        item { WorkoutItem(workoutItems.getAsState(index).value) } // triggers reload

        lastWorkout = workout 
    }
}

I believe the issue in your code was that you were calling this@LazyColumn from inside an LazyItemScope .我相信您的代码中的问题是您从 LazyItemScope 内部调用this@LazyColumn LazyItemScope

I experimented too with insertSeparators and reached this working LazyColumn code:我也尝试了insertSeparators并达到了这个工作 LazyColumn 代码:

LazyColumn {
    for (index in 0 until photos.itemCount) {
        when (val peekData = photos.peek(index)) {
            is String? -> stickyHeader {
                Text(
                    text = (photos.getAsState(index).value as? String).orEmpty(),
                )
            }
            is Photo? -> item(key = { peekData?.id }) {
                val photo = photos.getAsState(index).value as? Photo
                ...
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM