Hassan Alhajji
Hassan Alhajji

Reputation: 53

Jetpack Compose: How to change color of a button border depending on if it is enabled or disabled?

Is it possible to change the color of the border .border( when it is disabled? Something like ButtonDefaults.buttonColors to make border color Color.Gray if the button is disabled and keeping background transparent.

@Composable
fun MyButton(
    modifier: Modifier = Modifier,
    title: String,
    isEnabled: Boolean = true,
    onClick: () -> Unit
) {
    Button(
        modifier = modifier
            .height(40.dp)
            .border(
                width = 1.dp,
                color = Color.Red,
                shape = RoundedCornerShape(16.dp)
            )
            .background(
                color = Color.Transparent,
                shape = RoundedCornerShape(16.dp),
            ),
        shape = RoundedCornerShape(16.dp),
        onClick = onClick,
        elevation = ButtonDefaults.elevation(
            defaultElevation = 0.dp,
            pressedElevation = 0.dp,
            hoveredElevation = 0.dp
        ),
        colors = ButtonDefaults.buttonColors(
            backgroundColor = Color.Transparent,
            disabledBackgroundColor = Color.Transparent,
            contentColor = Color.White,
            disabledContentColor = Color.Gray
        ),
        enabled = isEnabled
    ) {
        Text(text = title)
    }
}

Upvotes: 5

Views: 6810

Answers (3)

jgodinez
jgodinez

Reputation: 81

Here's a working code 100%

Initialize the ButtonColors instance

val buttonColors: ButtonColors = ButtonColors(
                    containerColor = Color(0xFFDF2B51),
                    contentColor = Color(0xFF000000),
                    disabledContainerColor = Color(0xFFE6E6E6),
                    disabledContentColor = Color(0xFFAAAAAA),
                )

Then create an extension function for ButtonColors that gets the border color based on the state (enabled/disabled)

private fun ButtonColors.borderColor(enabled: Boolean): Color =
    if (enabled) contentColor else disabledContentColor

In your custom button create a variable that gets the value of the border and sets it to the color of the border stroke

val borderColor: Color = colors.borderColor(enabled)

Button(
    onClick = onClick,
    modifier = modifier,
    enabled = enabled,
    colors = colors,
    border = BorderStroke(1.dp, borderColor)
)

Full code sample:


Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    var enabled by rememberSaveable { mutableStateOf(true) }
                    val buttonColors: ButtonColors = ButtonColors(
                        containerColor = Color(0xFFDF2B51),
                        contentColor = Color(0xFF000000),
                        disabledContainerColor = Color(0xFFE6E6E6),
                        disabledContentColor = Color(0xFFAAAAAA),
                    )

                    Column(modifier = Modifier.padding(innerPadding)) {
                        Row(verticalAlignment = Alignment.CenterVertically) {
                            Checkbox(checked = enabled, onCheckedChange = { enabled = it })
                            Text("Enabled")
                        }
                        MyButton(
                            text = "Custom button",
                            onClick = { },
                            modifier = Modifier.padding(8.dp),
                            enabled = enabled,
                            colors = buttonColors
                        )
                    }
                }
...

private fun ButtonColors.borderColor(enabled: Boolean): Color =
    if (enabled) contentColor else disabledContentColor

@Composable
fun MyButton(
    text: String,
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    colors: ButtonColors = ButtonDefaults.buttonColors(),
) {
    val borderColor: Color = colors.borderColor(enabled)
    Button(
        onClick = onClick,
        modifier = modifier,
        enabled = enabled,
        colors = colors,
        border = BorderStroke(1.dp, borderColor)
    ) {
        Icon(
            imageVector = Icons.Default.Call,
            contentDescription = ""
        )
        Text(
            text = text,
            modifier = Modifier.padding(horizontal = 10.dp)
        )
    }
}

Enabled state Disabled state

Upvotes: 0

okmyan
okmyan

Reputation: 68

It would be better to use border parameter in Button function

Button(
    border = BorderStroke(
        width = 1.dp, 
        color = if (isEnabled) Color.Red else Color.Gray
    )
) { ... }

Upvotes: 1

Gabriele Mariotti
Gabriele Mariotti

Reputation: 364720

Just add a condition in the color attribute in the border modifier.

Something like:

.border(
    width = 1.dp,
    color = if (isEnabled) Color.Red else Color.Gray,
    shape = RoundedCornerShape(16.dp)
) 

Upvotes: 5

Related Questions