I have a problem with displaying the card when the checkbox is checked. I would like a given card in one activity to be displayed only when the user selects a given checkbox in another activity. But when I created a visibility condition, this card does not show even when this condition is met.
Here is code of the activity with checkboxes
package com.example.drzewogenealogiczne20.questionnaire
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Button
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.navigation.NavHostController
data class CheckboxItem(
val id: String,
val label: String,
val isChecked: Boolean
)
data class CardItem(
val id: String,
val title: String,
val checkboxes: List<CheckboxItem>,
val exclusiveCheckboxes: Boolean = false,
val visibleCondition: ((List<CardItem>) -> Boolean)? = null
)
class QuestionnaireViewModel : ViewModel() {
var cards by mutableStateOf<List<CardItem>>(emptyList())
private set
fun setAnswers(list: List<CardItem>) {
cards = list
}
}
@Composable
fun QuestionScreen(navController: NavHostController, viewModel: QuestionnaireViewModel) {
var cards by remember {
mutableStateOf(
listOf(
CardItem(
id = "card1",
title = "W którym wieku żyła poszukiwana osoba?",
exclusiveCheckboxes = false,
checkboxes = listOf(
CheckboxItem(
id = "checkbox1",
label = "XVIII (1701-1800)",
isChecked = false
),
CheckboxItem(
id = "checkbox2",
label = "XIX (1801-1900)",
isChecked = false
),
CheckboxItem(
id = "checkbox3",
label = "XX (1901-2000)",
isChecked = false
),
CheckboxItem(
id = "checkbox4",
label = "XXI (2001-2100)",
isChecked = false
),
)
),
visibleCondition = { allCards ->
allCards.find { it.id == "card1" }
?.checkboxes
?.find { it.id == "checkbox3" }?.isChecked == true
}
),
)
)
}
var validationError by remember { mutableStateOf<String?>(null) }
fun validate(): Boolean {
val visibleCards = cards.filter { it.visibleCondition?.invoke(cards) != false }
return visibleCards.all { card ->
card.checkboxes.any { it.isChecked }
}
}
fun onCheckboxChange(cardId: String, checkboxId: String, checked: Boolean) {
cards = cards.map { card ->
if (card.id == cardId) {
if (card.exclusiveCheckboxes) {
card.copy(
checkboxes = card.checkboxes.map {
if (it.id == checkboxId) it.copy(isChecked = checked)
else it.copy(isChecked = false)
}
)
} else {
card.copy(
checkboxes = card.checkboxes.map {
if (it.id == checkboxId) it.copy(isChecked = checked)
else it
}
)
}
} else card
}
viewModel.setAnswers(cards)
if (!validate()) {
validationError = "Zaznacz co najmniej jedną odpowiedź w każdej widocznej sekcji."
} else {
validationError = null
}
}
val visibleCards = cards.filter { it.visibleCondition?.invoke(cards) != false }
Column(Modifier.fillMaxSize()) {
LazyColumn(modifier = Modifier.weight(1f)) {
items(visibleCards) { card ->
CardItemView(card = card, onCheckboxChange = ::onCheckboxChange)
}
}
Button(
onClick = {
if (validate()) {
navController.navigate("result")
} else {
validationError = "Zaznacz co najmniej jedną odpowiedź w każdej widocznej sekcji."
}
},
enabled = validate(), // blokada przycisku
modifier = Modifier.fillMaxWidth()
) {
Text("Pokaż wynik")
}
validationError?.let { errorMsg ->
Text(
text = errorMsg,
color = Color.Red,
modifier = Modifier.padding(top = 8.dp)
)
}
}
}
@Composable
fun CardItemView(
card: CardItem,
onCheckboxChange: (String, String, Boolean) -> Unit
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
elevation = CardDefaults.cardElevation(6.dp)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(text = card.title, style = MaterialTheme.typography.titleMedium)
Spacer(modifier = Modifier.height(8.dp))
card.checkboxes.forEach { checkbox ->
Row(verticalAlignment = Alignment.CenterVertically) {
Checkbox(
checked = checkbox.isChecked,
onCheckedChange = { checked ->
onCheckboxChange(card.id, checkbox.id, checked)
}
)
Text(text = checkbox.label)
}
}
}
}
}
And the second activity with card I want to display depending of checkboxes
package com.example.drzewogenealogiczne20.questionnaire
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController
import com.example.drzewogenealogiczne20.questionnaire.QuestionScreen
data class CardResult(
val id: String,
val title: String,
val visibleCondition: ((List<CardItem>) -> Boolean)? = null
)
@Composable
fun ViewResults(
navController: NavHostController,
viewModel: QuestionnaireViewModel = viewModel()
) {
val answers = viewModel.cards
var cards by remember {
mutableStateOf(
listOf(
CardResult(
id = "FamilySearch",
title = "Family Search",
visibleCondition = { allCards ->
allCards.find { it.id == "card1" }
?.checkboxes
?.find { it.id == "checkbox1" }?.isChecked == true
}
),
)
)
}
val filteredCards = cards.filter { card ->
card.visibleCondition?.invoke(answers) ?: true
}
Column(
Modifier
.fillMaxSize()
.padding(16.dp)
) {
LazyColumn(modifier = Modifier.weight(1f)) {
items(filteredCards
) { card ->
CardResultView(card)
}
}
}
}
@Composable
fun CardResultView(
card: CardResult
) {
Card(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
elevation = CardDefaults.cardElevation(6.dp)
) {
Column(Modifier.padding(16.dp)) {
Text(text = card.title, style = MaterialTheme.typography.titleMedium)
Spacer(modifier = Modifier.height(8.dp))
}
}
}
visibleCondition. You can edit your question to fix it. Make sure you provide all code in the form of a minimal reproducible example.