Search code examples
androidandroid-jetpack-composeandroid-togglebutton

Create Toggle Button Group in Jetpack Compose without Radio Buttons


I am trying to put a button toggle group in my project that behaves similarly to a radio button group, but does not look like a radio button group (ie when one button is selected, the others are deselected).

I followed a radio button pattern I found online, but that doesn't seem to be doing the trick. Is there a way to do this? I've gotten to a point where I have the buttons in the place I want them, but they're both disabled.

MovieSpotterTheme() {
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                ) {
                    @Composable
                    fun MaterialButtonToggleGroup() {
                        var selected by remember { mutableStateOf("Android") }

                        val buttonGroup = listOf("Popular Movies", "Search Movies")

                     
                        val onSelectedChange = { text: String ->
                            selected = text
                        }
                        Row(
                            horizontalArrangement = Arrangement.SpaceEvenly
                        ) {
                            buttonGroup.forEach { text ->
                                Row(Modifier
                                    .selectable(
                                        selected = (text == selected),
                                        onClick = { onSelectedChange(text) }
                                    )
                                    .padding(horizontal = 16.dp)
                                ) {
                                    Button(
                                        enabled = (text == selected),
                                        onClick = { onSelectedChange(text) }
                                    ) {
                                        Column(
                                            horizontalAlignment = Alignment.CenterHorizontally
                                        ) {
                                            Text(
                                                text = text,
                                                style = MaterialTheme.typography.body1.merge(),
                                                modifier = Modifier.padding(horizontal = 16.dp)
                                            )
                                        }
                                    }
                                }
                            }
                        }
                    }
                    Surface() {
                        MaterialButtonToggleGroup()
                    }
                }
            }

Solution

  • Providing a simplified version. Play around with it to suit your requirement.

    @Composable
    fun CustomRadioGroup() {
        val options = listOf(
            "Option 1",
            "Option 2",
            "Option 3",
            "Option 4",
        )
        var selectedOption by remember {
            mutableStateOf("")
        }
        val onSelectionChange = { text: String ->
            selectedOption = text
        }
    
        Column(
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally,
            modifier = Modifier.fillMaxSize(),
        ) {
            options.forEach { text ->
                Row(
                    modifier = Modifier
                        .padding(
                            all = 8.dp,
                        ),
                ) {
                    Text(
                        text = text,
                        style = typography.body1.merge(),
                        color = Color.White,
                        modifier = Modifier
                            .clip(
                                shape = RoundedCornerShape(
                                    size = 12.dp,
                                ),
                            )
                            .clickable {
                                onSelectionChange(text)
                            }
                            .background(
                                if (text == selectedOption) {
                                    Color.Magenta
                                } else {
                                    Color.LightGray
                                }
                            )
                            .padding(
                                vertical = 12.dp,
                                horizontal = 16.dp,
                            ),
                    )
                }
            }
        }
    }
    

    Radio Group