You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

LazyColumn列表项中TextDecoration样式不生效问题排查

Troubleshooting Persistent Strikethrough in Jetpack Compose Todo App

Hey there! Let's figure out why that strikethrough won't disappear when your Todo items are marked as not done—even though the text color switches correctly. That's a tricky edge case, but let's break down the likely causes and fixes.

First, Diagnose the Core Issue

You mentioned the color toggles properly when todo.done changes, so we know the component is recomposing. The problem lies in why TextDecoration.None isn't overriding the strikethrough state when it should. Here are the most probable culprits:

1. Missing Unique Keys in LazyColumn

LazyColumn (formerly LazyColumnFor) reuses composable items to optimize performance. If you aren't assigning a unique key to each Todo item, it might retain the old strikethrough state when recycling components.

Fix: Always pass a unique identifier (like your TodoItem.id) when rendering items in LazyColumn:

LazyColumn {
    items(todoItems, key = { todoItem -> todoItem.id }) { todo ->
        Todo(todo = todo)
    }
}

This tells Compose exactly which item maps to which composable, preventing incorrect state reuse.

2. Recreated TextStyle Instances Triggering Unexpected Behavior

Right now, you're creating a new TextStyle instance every time TodoText recomposes. While Compose can handle this, caching these styles with remember helps Compose better track state changes and avoids edge cases where the style isn't updated correctly.

Fix: Cache your text styles using remember:

@Composable private fun TodoText(todo: TodoItem) {
    // Cache styles to avoid recreating them on every recomposition
    val doneStyle = remember {
        TextStyle(
            textDecoration = TextDecoration.LineThrough,
            color = Color.LightGray,
            fontSize = 18.sp,
        )
    }
    val normalStyle = remember {
        TextStyle(
            textDecoration = TextDecoration.None,
            color = Color.Black,
            fontSize = 18.sp,
        )
    }

    Text(
        text = todo.title,
        style = if (todo.done) doneStyle else normalStyle
    )
}

3. Ensure TodoItem State is Properly Observed

Double-check that your TodoItem updates trigger recompositions correctly. If you're holding your todo list in a regular variable instead of a Compose State (like mutableStateOf) or a flow (like StateFlow), Compose won't detect when todo.done changes.

Example of correct state handling in ViewModel:

class TodoViewModel : ViewModel() {
    private val _todoItems = mutableStateListOf<TodoItem>()
    val todoItems: List<TodoItem> get() = _todoItems

    fun toggleTodoDone(todoId: String) {
        val index = _todoItems.indexOfFirst { it.id == todoId }
        if (index != -1) {
            val existingTodo = _todoItems[index]
            _todoItems[index] = existingTodo.copy(done = !existingTodo.done)
        }
    }
}

Using mutableStateListOf ensures any changes to the list (or individual items) trigger recompositions.

Test These Fixes in Order

Start with adding the unique key to LazyColumn—this is the most common cause of state reuse issues in list components. If that doesn't fix it, move on to caching the text styles, then verify your state handling.

内容的提问来源于stack exchange,提问作者Fred

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 14:17:46