[英]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.