英文:
Change colour of "active" stickyHeader in a Jetpack Compose LazyColumn?
问题
以下是翻译好的内容:
"Is it possible to dynamically trigger the color
of the Surface
element that holds the stickyHeader
in the Composable below, so that only the header, which is currently at the top, has a colour, whereas the rest are either transparent or have the default background colour?
I have tried using .onGloballyPositioned
, but it produces strange behaviour, whereby the first header remains white, the second changes colour only when the third one becomes visible and the rest are always coloured, regardless of whether they are at the top."
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AphorismList(
navController: NavController,
contentItemsList: List<AphorismAndImage>
) {
val dateFormatter = DateTimeFormatter.ofPattern("MMMM")
val groupedAphorisms = contentItemsList.groupBy { it.contentItem.date?.format(dateFormatter) ?: LocalDate.now().month }
val listState = rememberLazyListState()
var stickyHeaderPosition = 1.0F
LazyColumn(
state = listState
) {
groupedContentItems.forEach { (header, contentItems) ->
stickyHeader {
Surface(
modifier = Modifier
.fillParentMaxWidth()
.onGloballyPositioned {
stickyHeaderPosition = it.positionInParent().y
},
color = if (stickyHeaderPosition == 0.0F) MaterialTheme.colorScheme.surfaceColorAtElevation(12.dp) else MaterialTheme.colorScheme.background
) {
Text(
text = header.toString().replaceFirstChar { it.uppercase() },
style = MaterialTheme.typography.labelLarge,
modifier = Modifier
.padding(8.dp)
)
}
}
items(contentItems) { contentItem ->
ContentListItem(contentItem, navController)
}
}
}
}
英文:
Is it possible to dynamically trigger the color
of the Surface
element that holds the stickyHeader
in the Composable below, so that only the header, which is currently at the top, has a colour, whereas the rest are either transparent or have the default background colour?
I have tried using .onGloballyPositioned
, but it produces strange behaviour, whereby the first header remains white, the second changes colour only when the third one becomes visible and the rest are always coloured, regardless of whether they are at the top.
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AphorismList(
navController: NavController,
contentItemsList: List<AphorismAndImage>
) {
val dateFormatter = DateTimeFormatter.ofPattern("MMMM")
val groupedAphorisms = contentItemsList.groupBy { it.contentItem.date?.format(dateFormatter) ?: LocalDate.now().month }
val listState = rememberLazyListState()
var stickyHeaderPosition = 1.0F
LazyColumn(
state = listState
) {
groupedContentItems.forEach { (header, contentItems) ->
stickyHeader {
Surface(
modifier = Modifier
.fillParentMaxWidth()
.onGloballyPositioned {
stickyHeaderPosition = it.positionInParent().y
},
color = if (stickyHeaderPosition == 0.0F) MaterialTheme.colorScheme.surfaceColorAtElevation(12.dp) else MaterialTheme.colorScheme.background
) {
Text(
text = header.toString().replaceFirstChar { it.uppercase() },
style = MaterialTheme.typography.labelLarge,
modifier = Modifier
.padding(8.dp)
)
}
}
items(contentItems) { contentItem ->
ContentListItem(contentItem, navController)
}
}
}
}
答案1
得分: 2
I guess using same variable for all the headers is causing that behavior, you could create a mutableStateOf<Header>
to hold current sticked header and update it in onGloballyPositioned
and change colour if current header matches the state value
val currentHeaderState = remember { mutableStateOf<String?>(null) }
LazyColumn(
state = listState, userScrollEnabled = true
) {
groupedContentItems.forEach { (header, contentItems) ->
stickyHeader {
Surface(
modifier = Modifier
.fillParentMaxWidth()
.onGloballyPositioned {
if (it.positionInParent().y == 0.0F) {
currentHeaderState.value = header
}
},
color = if (header == currentHeaderState.value)
Color.Blue
else Color.Red
) {
Text(
text = header.replaceFirstChar { it.uppercase() },
modifier = Modifier
.padding(8.dp)
)
}
}
items(contentItems){ item ->
Text(
text = item,
modifier = Modifier
.padding(8.dp)
)
}
}
}
英文:
I guess using same variable for all the headers is causing that behavior, you could create a mutableStateOf<Header>
to hold current sticked header and update it in onGloballyPositioned
and change colour if current header matches the state value
val currentHeaderState = remember { mutableStateOf<String?>(null) }
LazyColumn(
state = listState, userScrollEnabled = true
) {
groupedContentItems.forEach { (header, contentItems) ->
stickyHeader {
Surface(
modifier = Modifier
.fillParentMaxWidth()
.onGloballyPositioned {
if(it.positionInParent().y == 0.0F){
currentHeaderState.value = header
}
},
color = if (header == currentHeaderState.value)
Color.Blue
else Color.Red
) {
Text(
text = header.replaceFirstChar { it.uppercase() },
modifier = Modifier
.padding(8.dp)
)
}
}
items(contentItems){ item ->
Text(
text = item,
modifier = Modifier
.padding(8.dp)
)
}
}
}
答案2
得分: 1
以下是您要翻译的代码部分:
感谢 Rajan Kali,经过一些微小的调整,我成功使其工作。
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AphorismList(
navController: NavController,
contentItemsList: List<AphorismAndImage>
) {
val dateFormatter = DateTimeFormatter.ofPattern("MMMM")
val groupedAphorisms = contentItemsList.groupBy { it.contentItem.date?.format(dateFormatter) ?: LocalDate.now().month }
val listState = rememberLazyListState()
val currentHeaderState = remember { mutableStateOf<String?>(null) }
LazyColumn(
state = listState
) {
groupedContentItems.forEach { (header, contentItems) ->
stickyHeader {
Surface(
modifier = Modifier
.fillParentMaxWidth()
.onGloballyPositioned {
currentHeaderState.value = header.toString()
},
color = if (header == currentHeaderState.value && listState.firstVisibleItemIndex > 0) MaterialTheme.colorScheme.surfaceColorAtElevation(12.dp) else MaterialTheme.colorScheme.background
) {
Text(
text = header.toString().replaceFirstChar { it.uppercase() },
style = MaterialTheme.typography.labelLarge,
modifier = Modifier
.padding(8.dp)
)
}
}
items(contentItems) { contentItem ->
ContentListItem(contentItem, navController)
}
}
}
}
英文:
Thanks to Rajan Kali, and after a few tiny tweaks, I managed to get it working.
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun AphorismList(
navController: NavController,
contentItemsList: List<AphorismAndImage>
) {
val dateFormatter = DateTimeFormatter.ofPattern("MMMM")
val groupedAphorisms = contentItemsList.groupBy { it.contentItem.date?.format(dateFormatter) ?: LocalDate.now().month }
val listState = rememberLazyListState()
val currentHeaderState = remember { mutableStateOf<String?>(null) }
LazyColumn(
state = listState
) {
groupedContentItems.forEach { (header, contentItems) ->
stickyHeader {
Surface(
modifier = Modifier
.fillParentMaxWidth()
.onGloballyPositioned {
currentHeaderState.value = header.toString()
},
color = if (header == currentHeaderState.value && listState.firstVisibleItemIndex > 0) MaterialTheme.colorScheme.surfaceColorAtElevation(12.dp) else MaterialTheme.colorScheme.background
) {
Text(
text = header.toString().replaceFirstChar { it.uppercase() },
style = MaterialTheme.typography.labelLarge,
modifier = Modifier
.padding(8.dp)
)
}
}
items(contentItems) { contentItem ->
ContentListItem(contentItem, navController)
}
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论