安卓传统的 Recyclerview 打造悬浮头部StickyHeader的吸顶效果,十分麻烦,而在Compose中就简单多了
stickyHeader
Compose设计的时候考虑得很周到,他们提供了stickyHeader
作用就是添加一个粘性标题项,即使在它后面滚动时也会保持固定。标头将保持固定,直到下一个标头取而代之。
参数key - 表示唯一的密钥键。
它不允许对列表出现使用相同的键。密钥的类型应该可以通过 Bundle
保存。如果传递了 null
,则列表中的位置将代表键。当指定键时,滚动位置将基于该键保持,这意味着如果在当前可见项目之前添加删除项目,则具有给定键的项目将保留为第一个可见项目。
参数content 传入Composable控件就即可显示
实体类
创建一个实体类标题和内容
data class Post(
val title:String,
val contentData:List<String>
)
加载假数据
val list : MutableList<Post> = mutableListOf()
for (index in 1..10) {
val contentData :MutableList<String> = mutableListOf()
for (i in 1..30){
contentData.add("内容 $i")
}
list.add(Post("标题$index",contentData))
}
定义一个垂直滚动列表,仅构成和布局当前可见的项目
LazyColumn {
list.forEachIndexed { position, post ->
stickyHeader {
ListTitle(title = post.title)
}
items(post.contentData.size) { route ->
StructureItem(post.contentData)
}
if (position <= list.size - 1) {
Divider()
}
Spacer(modifier = Modifier.height(10.dp))
}
}
吸顶标题
接着封装一个吸顶标题,并传出点击事件
@Composable
fun ListTitle(
onSubtitleClick: () -> Unit = {}
) {
MediumTitle(
title = title,
modifier = Modifier.align(Alignment.CenterVertically).clickable {
onSubtitleClick.invoke()
}
}
效果图
二级条目
接着写二级条目
FlowRow
可以将其子项置于水平流中的可组合项。如果水平空间太小而无法将所有子项放在一行中,则可能会使用多行。传统的流式布局
用法很简单,和row一样
FlowRow {
for (item in bean) {
TextButton(
....
}
}
}
在content可组控件里面添加多个TextButton即可
fun StructureItem{
Column{
FlowRow() {
for (item in bean) {
TextButton
{
Text()
}
}
}
}
}
效果图
接着吸顶标题放在LazyColumn里面就完成了
LazyColumn() {
list.forEachIndexed { position, post ->
stickyHeader {
ListTitle(title = post.title) {
//点击事件
}
}
item {
StructureItem(post.contentData)
Spacer(modifier = Modifier.height(10.dp))
}
}
}
完整代码
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun StickyHeaderScreen() {
val list: MutableList<Post> = mutableListOf()
for (index in 1..10) {
val contentData: MutableList<String> = mutableListOf()
for (i in 1..12) {
contentData.add("内容 $i")
}
list.add(Post("标题$index", contentData))
}
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(),
contentPadding = PaddingValues(vertical = 10.dp)
) {
list.forEachIndexed { position, post ->
stickyHeader {
ListTitle(title = post.title) {
//点击事件
}
}
item {
StructureItem(post.contentData)
Spacer(modifier = Modifier.height(10.dp))
}
}
}
}
data class Post(
val title: String,
val contentData: List<String>
)
@Composable
fun ListTitle(
modifier: Modifier = Modifier,
title: String,
isLoading: Boolean = false,
onSubtitleClick: () -> Unit = {}
) {
Row(
modifier = modifier
.placeholder(false)
.fillMaxWidth()
.height(ListTitleHeight)
.background(color = Color.Gray)
) {
Box(
modifier = Modifier
.padding(horizontal = 10.dp)
.width(5.dp)
.height(16.dp)
.align(Alignment.CenterVertically)
.background(color = Color.Black)
)
MediumTitle(
title = title,
color = Color.Black,
modifier = Modifier.align(Alignment.CenterVertically).clickable {
onSubtitleClick.invoke()
},
isLoading = isLoading
)
Spacer(modifier = Modifier.weight(1f))
}
}
@Composable
fun StructureItem(
bean: List<String>
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(top = 10.dp)
) {
FlowRow(
modifier = Modifier.padding(horizontal = 6.dp)
) {
for (item in bean) {
Box(modifier = Modifier.padding(horizontal = 2.dp, vertical = 3.dp)) {
TextButton(
modifier = Modifier.padding(horizontal = 3.dp).height(34.dp),
shape = RoundedCornerShape(12.dp),
onClick = { },
colors = ButtonDefaults.textButtonColors(
backgroundColor = themeColor
)
)
{
Text(
item,
color = Color.White
)
}
}
}
}
}
}
效果图
左边的黑边是我裁剪的问题,抱歉啦!
到此这篇关于Android Jetpack Compose实现列表吸顶效果的文章就介绍到这了,更多相关Jetpack Compose列表吸顶内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!