androidandroid-jetpack-composematerial-components-android

How to change CheckBox icons more effectively in jetpack compose


ok so i have two rows of checkboxes that the user can either press checked or uncheked to each individual column so i came up with this idea of code :

fun HowAmIDoingComponent(
    modifier: Modifier = Modifier,
    selfAssessmentList: List<SelfAssessmentTableInfo>,
    onSelectAnswer: (SelfAssessmentTableInfo) -> Unit
) {
    var checkboxPairsStates by remember {
        mutableStateOf(
            selfAssessmentList.map { Pair(false, false) }
        )
    }
    Column(modifier = modifier.background(WizardTheme.colors.white)) {
        selfAssessmentList.mapIndexed { index, selfAssessment ->
            val pairState = checkboxPairsStates[index]
            Row(
                modifier = modifier
                    .fillMaxWidth()
                    .height(IntrinsicSize.Min)
                    .padding(vertical = dimensionResource(id = R.dimen.smallest_margin))
            ) {
                Column(
                    modifier = Modifier
                        .weight(4f)
                        .align(Alignment.CenterVertically)
                ) {
                    BodyTextComponent(text = selfAssessment.title ?: Empty())
                }
                Box(
                    modifier = Modifier
                        .weight(1.5f)
                        .fillMaxHeight(),
                    contentAlignment = Alignment.Center
                ) {
                    CustomCheckbox(
                        iconVectorPositive = ImageVector.vectorResource(id = R.drawable.ic_checked),
                        iconVectorNegative = ImageVector.vectorResource(id = R.drawable.ic_rectangle),
                        checked = pairState.first,
                        onCheckedChange = { isChecked ->
                            onSelectAnswer(selfAssessment)
                            checkboxPairsStates = checkboxPairsStates.toMutableList().apply {
                                set(index, Pair(isChecked, false))
                            }
                        },

                        modifier = Modifier
                            .padding(8.dp)
                            .size(30.dp)
                    )
                }
                Box(
                    modifier = Modifier
                        .weight(1.5f)
                        .fillMaxHeight(),
                    contentAlignment = Alignment.Center
                ) {
                    CustomCheckbox(
                        iconVectorPositive = ImageVector.vectorResource(id = R.drawable.ic_option_no),
                        iconVectorNegative = ImageVector.vectorResource(id = R.drawable.ic_rectangle),
                        checked = pairState.second,
                        onCheckedChange = { isChecked ->
                            onSelectAnswer(selfAssessment)
                            checkboxPairsStates = checkboxPairsStates.toMutableList().apply {
                                set(index, Pair(false, isChecked))
                            }
                        },
                        modifier = Modifier
                            .padding(8.dp)
                            .size(30.dp)
                    )
                }
                MediumSpacer()
            }
            Divider(
                color = WizardTheme.colors.greyLightest,
                thickness = dimensionResource(id = R.dimen.border_stroke)
            )
        }
    }
}

@Composable
fun CustomCheckbox(
    iconVectorPositive: ImageVector,
    iconVectorNegative: ImageVector,
    checked: Boolean,
    onCheckedChange: (Boolean) -> Unit,
    modifier: Modifier
) {
    val iconVector: ImageVector = if (checked) {
        iconVectorPositive
    } else {
        iconVectorNegative
    }
    Icon(
        imageVector = iconVector,
        contentDescription = stringResource(R.string.custom_checkbox),
        tint = Color.Unspecified,
        modifier = modifier.clickable { onCheckedChange(!checked) }
    )
}

this works nicely.... all i do in my viewModel is manage that specificObject he clicked and put it in a list to be sent to the back end and saved as a valid answer.

But for some reason this approach is somehow "slow" and is compromising some slower devices. If i use an android 12 with a slower phone , my checkboxes TICKS dont register unless i change the state of the screen like getting out and back in to the app or pressing something else that doenst involve checkboxes and then they all show up as ticked as they should.

If i use a faster phone i dont get that error at all everything works fine..

So as a " new " compose developer, what exactly am i doing wrong here ? and what could be improved ?

This is what i achieved with this approach : enter image description here


Solution

  • Ok so apparently the fact taht i was using A VECTOR instead of a painterResource was really overloading low end devices.

    so this was the approach i went with =

       @Composable
    fun CustomCheckbox(
        iconResIdPositive: Int,
        iconResIdNegative: Int,
        checked: Boolean,
        onCheckedChange: (Boolean) -> Unit,
        modifier: Modifier
    ) {
        val iconResId: Int = if (checked) {
            iconResIdPositive
        } else {
            iconResIdNegative
        }
        val painter = painterResource(id = iconResId)
        Image(
            painter = painter,
            contentDescription = stringResource(R.string.custom_checkbox),
            modifier = modifier.clickable { onCheckedChange(!checked) }
        )
    }
    

    this solved my issue of checkBox not being ticked :D