更改 Jetpack Compose LazyColumn 中“active” stickyHeader 的颜色?

huangapple go评论59阅读模式
英文:

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

huangapple
  • 本文由 发表于 2023年5月13日 17:31:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76242007.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定