wbk727
wbk727

Reputation: 8408

Single choice dialog item text not aligned with radio buttons

For some reason the Text components are not exactly aligned vertically as the radio buttons in my dialog. I tried adjusting the padding values in every part but there is still not any effect.

@Composable
fun CommonDialog(
    title: String?,
    state: MutableState<Boolean>,
    content: @Composable (() -> Unit)? = null
) {
    AlertDialog(
        onDismissRequest = {
            state.value = false
        },
        title = title?.let {
            {
                Column(
                    Modifier.fillMaxWidth(),
                    verticalArrangement = Arrangement.spacedBy(5.dp)
                ) {
                    Text(text = title)
                }
            }
        },
        text = content,
        confirmButton = {
            TextButton(onClick = { state.value = false }) {
                Text(stringResource(id = R.string.button_cancel))
            }
        }, modifier = Modifier.padding(vertical = 5.dp)
    )
}

@Composable
fun AlertSingleChoiceView(state: MutableState<Boolean>) {
    CommonDialog(title = stringResource(id = R.string.theme), state = state) {
        SingleChoiceView()
    }
}

@Composable
fun SingleChoiceView() {
    val radioOptions = listOf(
        stringResource(id = R.string.straight),
        stringResource(id = R.string.curly),
        stringResource(id = R.string.wavy))
    val (selectedOption, onOptionSelected) = remember { mutableStateOf(radioOptions[2]) }
    Column(
        Modifier.fillMaxWidth()
    ) {
        radioOptions.forEach { text ->
            Row(
                Modifier
                    .fillMaxWidth()
                    .selectable(
                        selected = (text == selectedOption),
                        onClick = {
                            onOptionSelected(text)
                        }
                    )
                    .padding(vertical = 5.dp)
            ) {
                RadioButton(
                    selected = (text == selectedOption),
                    onClick = { onOptionSelected(text) }
                )
                Text(
                    text = text
                )
            }
        }
    }
}

Current result

enter image description here

Upvotes: 3

Views: 1254

Answers (2)

Ahmed Maad
Ahmed Maad

Reputation: 551

Problem:

Just in case anyone is facing an issue with Centering the RadioButton composable along with the Text composable vertically & horizontally like in the image:

Radio Buttons not Centered

Why does this happen?

Using the following code will result in non-centered radio buttons because the Column (1) composable is the first layout node to be composed before its child Row (3); that's why the horizontalAlignment (2) will center each drawn Row (3) separately according to the Row (3) children, the RadioButton and the Text composables.

You can check Jetpack Compose phases for more information:

Column( //--> (1)
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally, //--> (2)
        modifier = modifier.fillMaxSize()
    ) {
        var selectedRadioButton by remember { mutableStateOf("Small Font") }

        val options = arrayOf("Small Font", "Medium Font", "Large Font")

        options.forEach { item ->
            Row( //--> (3)
                verticalAlignment = Alignment.CenterVertically,
                modifier = modifier.selectable(
                    selected = selectedRadioButton == item,
                    onClick = { selectedRadioButton = item }
                )
            ) {
                RadioButton(
                    selected = selectedRadioButton == item,
                    onClick = {
                        selectedRadioButton = item
                    })
                Text(
                    text = item,
                    style = MaterialTheme.typography.bodyLarge,
                )
            }
        }
    }

Solution:

To solve this issue, we have to make sure that the three Row composables that contain the RadioButton and the Text composables will be centered as a whole block by using another Column (The answer) composable to be placed after the first Column composable (note: This example contains three rows because we are looping on an array with three elements).

Now, Column (1) composable will align its new child Column (The answer) composable to be centered correctly.

Column( //--> (1)
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
        modifier = modifier.fillMaxSize()
    ) {
        Column { //--> (The answer)
            var selectedRadioButton by remember { mutableStateOf("Small Font") }

            val options = arrayOf("Small Font", "Medium Font", "Large Font")

            options.forEach { item ->
                Row(
                    verticalAlignment = Alignment.CenterVertically,
                    modifier = modifier.selectable(
                        selected = selectedRadioButton == item,
                        onClick = { selectedRadioButton = item }
                    )
                ) {
                    RadioButton(
                        selected = selectedRadioButton == item,
                        onClick = {
                            selectedRadioButton = item
                        })
                    Text(
                        text = item,
                        style = MaterialTheme.typography.bodyLarge,
                    )
                }
            }
        }
    }

Centered Radio Buttons

Upvotes: 0

nglauber
nglauber

Reputation: 23894

You just need to set the verticalAlignment param for the Row.

Row(
    Modifier
        .fillMaxWidth()
        .selectable(
            selected = (text == selectedOption),
            onClick = {
                onOptionSelected(text)
            }
        )
        .padding(vertical = 5.dp),
    verticalAlignment = Alignment.CenterVertically // <<<< THIS
) {
   ...
}

Upvotes: 7

Related Questions