【问题标题】:Sticky headers with paging library in Jetpack ComposeJetpack Compose 中带有分页库的粘性标头
【发布时间】:2021-05-22 13:19:29
【问题描述】:

我目前正在使用新的 Jetpack compose UI 工具包,我非常喜欢它。我想不通的一件事是如何在由分页库填充的LazyColumn 中使用stickyHeadersdocumentation 中的非分页示例是:

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)
            }
        }
    }
}

由于我使用的是分页库,我无法使用groupedBy,所以我尝试在PagingData 上使用insertSeparators 函数并自己插入/创建标题(请忽略旧的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)
        }
    }
}

但这会生成我所有项目的列表,并且标题项目附加在末尾。任何想法在使用分页库时使用stickyHeader 函数的正确方法是什么?

【问题讨论】:

    标签: android android-jetpack-compose android-paging-library


    【解决方案1】:

    我通过查看items 函数的源代码使其工作:您不能在items 函数中调用stickyHeader。根本不需要修改 PagingData 流。只需使用 peek 获取下一个项目而不触发重新加载,然后对其进行布局:

    LazyColumn {
        var lastWorkout: Workout? = null
    
        for(index in workoutItems.indices) {
            val workout = workoutItems.peek(index)
    
            if(lastWorkout?.time != workout?.time) stickyHeader { Header(workout) }
            item { WorkoutItem(workoutItems.getAsState(index).value) } // triggers reload
    
            lastWorkout = workout 
        }
    }
    

    【讨论】:

    • 谢谢。数据显示正确,但是当我将新项目滚动到视图中(或向上滚动)时,某些项目的内容变得不可见。我认为这与撰写没有检测到它在屏幕上有关,所以它只是跳过渲染。这也是你经历过的事情吗?
    • 我没有,请务必致电workoutItems.getAsState(index).value,因为这会触发分页库的重新加载。不要使用peek 获得的项目进行布局。
    【解决方案2】:

    我认为您代码中的问题是您从 LazyItemScope 内部调用了 this@LazyColumn

    我也用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
                    ...
                }
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2022-08-23
      • 2012-12-28
      • 2021-12-28
      • 1970-01-01
      • 1970-01-01
      • 2017-02-05
      • 2021-11-06
      • 1970-01-01
      • 2020-03-11
      相关资源
      最近更新 更多