Как изменить цвет границы карты при нажатии на карту в Jetpack Compose?

У меня есть список пользователей, который отображается в ленивой строке. Каждая строка представлена ​​картой. Каждая карта имеет красную рамку. Как я могу изменить границу карты с красной на черную при нажатии на карту?

Вот что я пробовал:

      LazyRow(
    modifier = Modifier.fillMaxWidth()
) {
    items(users) { user ->
        UserCard(
            name = user.name
        )
    }
}

А вот и карта:

      fun UserCard(
    name: String
) {
    Card(
        modifier = Modifier.fillMaxWidth()
        border = BorderStroke(2.dp, Color.Red),
        onClick = { ??? }
    ) {
        Text(
            text = name
        )
    }
}

2 ответа

Вы можете использовать что-то вроде:

      var cardColor by remember { mutableStateOf(Red)}

Card(
    //..
    border = BorderStroke(2.dp, cardColor),
    onClick = { cardColor = Blue }
) {
    Text(
        text = "name"
    )
}

Если вы хотите обработать выбранное состояние, вы можете использовать что-то вроде:

      var selectedCard by remember { mutableStateOf(false) }
var cardColor = if (selectedCard) Red else Black

Card(
    border = BorderStroke(2.dp, cardColor),
    onClick = { selectedCard = !selectedCard }
) {
    Text(
        text = "name"
    )
}

Если вы хотите иметь Composable с отслеживанием состояния, вы можете сделать это, сохранив цвет внутри запоминания с помощью MutableState и изменив его по щелчку. Однако это будет сброшено, когда вы прокрутите назад к тому же элементу, потому что он будет перекомпонован, когда он снова появится на экране и будет иметь состояние, которое не рекомендуется. Официальный документ о господъеме .

      fun UserCard(
    name: String
) {

    var color by remember {mutableStateOf(Color.Red)}
    Card(
        modifier = Modifier.fillMaxWidth()
        border = BorderStroke(2.dp, color),
        onClick = { color = Color.Black}
    ) {
        Text(
            text = name
        )
    }
}

Если вы хотите иметь Composable без сохранения состояния, вы можете сделать это с помощью повышения состояния. В отличие от приведенного выше, этот будет иметь тот же цвет, даже если вы прокрутите вниз и вернетесь вверх, когда новые элементы будут перекомпонованы с существующим цветом границы.

      data class User(val name: String, var color: Color = Color.Red)

@Composable
private fun BorderList() {
    val userList = remember {
        mutableStateListOf<User>().apply {
            repeat(100) {
                add(User("User $it"))
            }
        }
    }

    LazyColumn {
        itemsIndexed(userList) { index, user ->
            UserCard(name = user.name, borderColor = user.color) {

                val newColor = if(user.color == Color.Red) Color.Black else Color.Red
                userList[index] = user.copy(color = newColor)
            }
        }
    }
}

@Composable
fun UserCard(
    name: String,
    borderColor: Color,
    onColorChange: () -> Unit
) {
    Card(
        modifier = Modifier.fillMaxWidth(),
        border = BorderStroke(2.dp, borderColor),
        onClick = { onColorChange() }
    ) {
        Text(
            text = name
        )
    }
}