Jetpack Compose is Android’s modern UI toolkit designed to simplify and accelerate UI development. Among its many features, the Button
composable stands out as a fundamental element for user interaction. However, the default Button
might not always align with your app’s design aesthetics. Fortunately, Jetpack Compose offers extensive customization options, allowing you to tailor the appearance and behavior of your buttons to create a unique user experience. In this blog post, we will delve into the various ways you can customize buttons in Jetpack Compose.
Why Customize Buttons in Jetpack Compose?
Customizing buttons is essential for:
- Branding Consistency: Ensures that buttons match your app’s overall design and brand identity.
- Enhanced User Experience: Creates visually appealing and intuitive interfaces.
- Improved Accessibility: Tailors button styles to meet accessibility standards, ensuring usability for all users.
Basic Button Customization
Let’s start with the fundamental customizations you can apply directly to the Button
composable.
1. Text and Content
The simplest customization is changing the button’s text. You can also add leading and trailing icons to provide visual context.
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.material.Icon
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
@Composable
fun MyCustomButton() {
Button(onClick = { /* Handle button click */ }) {
Icon(imageVector = Icons.Filled.Favorite, contentDescription = "Favorite Icon")
Text("Add to Favorites")
}
}
@Preview
@Composable
fun PreviewMyCustomButton() {
MyCustomButton()
}
2. Colors
You can modify the background and text colors of the button using the colors
parameter.
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.material.ButtonDefaults
import androidx.compose.ui.graphics.Color
@Composable
fun MyColoredButton() {
Button(
onClick = { /* Handle button click */ },
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Green,
contentColor = Color.White
)
) {
Text("Save Changes")
}
}
@Preview
@Composable
fun PreviewMyColoredButton() {
MyColoredButton()
}
3. Shape and Elevation
The button’s shape can be altered using the shape
parameter, and its elevation (shadow) can be adjusted for different states (e.g., pressed, enabled, disabled) using the elevation
parameter.
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.unit.dp
import androidx.compose.material.ButtonDefaults
import androidx.compose.ui.graphics.Color
@Composable
fun MyRoundedButton() {
Button(
onClick = { /* Handle button click */ },
shape = RoundedCornerShape(16.dp),
elevation = ButtonDefaults.elevation(
defaultElevation = 6.dp,
pressedElevation = 12.dp
),
colors = ButtonDefaults.buttonColors(
backgroundColor = Color.Blue,
contentColor = Color.White
)
) {
Text("Continue")
}
}
@Preview
@Composable
fun PreviewMyRoundedButton() {
MyRoundedButton()
}
Advanced Button Customization
For more advanced customizations, you can create custom button styles using CompositionLocalProvider
or by building a completely custom button composable.
1. Using CompositionLocalProvider
CompositionLocalProvider
allows you to provide custom values for pre-defined composable attributes, affecting all child composables. This is useful for applying a consistent style across your app.
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.material.LocalTextStyle
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.graphics.Color
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.unit.sp
import androidx.compose.ui.text.font.FontWeight
@Composable
fun MyAppTheme(content: @Composable () -> Unit) {
CompositionLocalProvider(
LocalTextStyle provides TextStyle(
fontSize = 18.sp,
fontWeight = FontWeight.Bold,
)
) {
content()
}
}
@Composable
fun MyThemedButton() {
Button(onClick = { /* Handle button click */ }) {
Text("Get Started")
}
}
@Preview
@Composable
fun PreviewMyThemedButton() {
MyAppTheme {
MyThemedButton()
}
}
2. Creating a Custom Button Composable
For maximum control, create a custom button composable. This approach allows you to define the layout, styling, and behavior of the button from scratch.
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
@Composable
fun CustomButton(text: String, onClick: () -> Unit) {
Box(
modifier = Modifier
.clickable(onClick = onClick)
.background(Color.Magenta)
.padding(16.dp),
contentAlignment = Alignment.Center
) {
Text(text = text, color = Color.White, fontSize = 20.sp)
}
}
@Preview
@Composable
fun PreviewCustomButton() {
CustomButton(text = "Click Me") {
// Handle button click
}
}
3. Styling Enabled/Disabled States
Handling enabled and disabled states effectively improves the usability of your app. You can apply different styles based on the enabled
state of the button.
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.material.ButtonDefaults
import androidx.compose.ui.graphics.Color
@Composable
fun MyStyledButton(enabled: Boolean = true) {
Button(
onClick = { /* Handle button click */ },
enabled = enabled,
colors = ButtonDefaults.buttonColors(
backgroundColor = if (enabled) Color.Blue else Color.Gray,
contentColor = Color.White
)
) {
Text("Submit")
}
}
@Preview
@Composable
fun PreviewMyStyledButtonEnabled() {
MyStyledButton(enabled = true)
}
@Preview
@Composable
fun PreviewMyStyledButtonDisabled() {
MyStyledButton(enabled = false)
}
Conclusion
Customizing buttons in Jetpack Compose offers endless possibilities for creating visually appealing and functional UI elements. Whether you’re tweaking basic attributes like colors and shapes, applying consistent styles through CompositionLocalProvider
, or crafting fully custom button composables, the power is in your hands. Experiment with these techniques to build buttons that elevate the user experience of your Android apps.