Developing a user interface in Android applications requires attention to the smallest details, and one of the most common tasks is customizing standard controls. Button (Button) is a key element interaction, which should not only fulfill its function, but also correspond to the visual concept of your product. Unlike web development, where styling often seems intuitive, in Android there are several layers of abstraction, from simple attributes to complex themes and styles that control the appearance of components.
Beginner developers often find that simply assigning a color via an attribute android:background leads to the loss of standard effects pressing (ripple effect) and rounding corners, making the button โflatโ and unnatural for the user. Modern versions of Android Studio and support libraries such as Material Componentsoffer more flexible tools for palette management. Understanding the difference between background color, text color and outline color is critical to creating a professional UI.
In this article we will look at everything in detail Available methods for changing button color: from the classic XML approach to modern solutions in Jetpack Compose. We'll look at how to properly use color resources, how to use application themes to change the style globally, and how to avoid common pitfalls associated with overriding system attributes. Ready to turn gray standard buttons into a bright element of your interface?
Basic styling via XML attributes
The easiest and most obvious way to change the appearance of a button is to directly edit the XML layout. However, here lies the first pitfall: using the attribute android:background completely replaces the standard widget background, removing the built-in click animations. If you simply specify the hex code of the color, the button will become a static rectangle.
For correct operation in modern versions of Android, it is recommended to use the attribute android:backgroundTint instead of completely replacing the background. This option overlays the color on top of an existing drawable resource while preserving the shape, shadows, and interaction effects. You can set a specific color directly in the layout or, more architecturally correct, reference the resource in a file colors.xml.
An example of using tint to change the background color is as follows:
<Buttonandroid:id="@+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Click me"
android:backgroundTint="@color/my_custom_blue"
android:textColor="@android:color/white" />
Note the usage android:textColor. By default, the text on a colored button may become unreadable (for example, black text on a dark blue background). Always check the contrast. If you're using MaterialButton from the component library, the approach changes slightly, since the widget has its own attributes to control the background and stroke, overriding the standard properties of the parent Button class.
Use vector drawables instead of simple background colors if you need complex gradients or shapes, but use backgroundTint for quick theme changes.
Use of Material Components and Styles
Library Material Components for Android has become the de facto standard for creating modern interfaces. The component com.google.android.material.button.MaterialButton provides an extended set of attributes that allow you to fine-tune the appearance without creating custom drawable files. This is especially useful when you need to change not only the color, but also the shape, stroke or icon.
To change the background color in the MaterialButton, the attribute is used app:backgroundTint, rather than the standard Android attribute. In addition, you can easily add a stroke around the button, setting its color and thickness. This opens up the possibility of creating buttons with a transparent background and a colored border, which is often used in secondary action designs.
- ๐จ app:backgroundTint โ Sets the primary fill color of the button.
- ๐๏ธ app:strokeColor โ Sets the color of the outline around the button.
- ๐ app:strokeWidth โ Determines the thickness of the stroke line in pixels or dp.
- ๐ app:iconTint โ allows you to change the color of the icon added inside the button.
android.com/apk/res-auto". Without this declaration, the compiler will throw an error and the styling will not be applied. It is also worth considering that MaterialButton automatically adapts to the dark theme if you have correctly configured semantic colors in the application theme.
โ ๏ธ Attention: Do not mix attributesandroid:backgroundandapp:backgroundTintin one MaterialButton element. This can lead to unpredictable results when one attribute overwrites another, breaking the visual integrity of the component.
Working with color resources and themes
Hardcoding colors (for example, #FF0000) directly in XML layouts are considered bad practice in professional development. This makes the code difficult to maintain and makes it impossible to quickly change the color scheme of the entire application. The correct approach is to put all the color values in a file. Creating a centralized color store allows you to change the color of a button throughout the application by editing just one line of code. It also opens the door to implementing a dark theme (Dark Mode). data-i="77">in the folder res/values/colors.xml.
Creating a centralized color store allows you to change the hue of a button across your entire application by editing just one line of code. In addition, this paves the way for the implementation of a dark theme (Dark Mode). You can create an alternative file colors.xml in a folder values-night, where the same resource names will refer to dark or inverted shades.
The structure of the resource file may look like this:
<resources><color name="primary_button_color">#6200EE</color>
<color name="on_primary_button_color">#FFFFFF</color>
<color name="secondary_button_stroke">#6200EE</color>
</resources>
When using Themes, you can set the button color globally for the entire application or a specific Activity In the file themes.xml you can override the attribute colorPrimary or create your own button style that will be applied automatically. This eliminates the need to manually assign colors for each button.
| Resource type | Location | Usage example | Advantage |
|---|---|---|---|
| Hex code | Inside layout XML | #FF5733 |
Fast for prototype |
| Color Resource | res/values/colors.xml |
@color/primary |
Easy support and theming |
| Theme Attribute | res/values/themes.xml |
?attr/colorPrimary |
Global style management |
| Color State List | res/color/ |
@color/button_states |
Different colors for different states |
Using Color State List (list of color states) is an advanced method that allows you to set different colors for the states pressed (pressed), enabled (active) and disabled (inactive) This greatly improves the user experience by providing visual feedback during interaction.
Programmatic color change in Kotlin and Java
Sometimes the color of a button needs to change dynamically depending on application logic, form state, or user actions. In such cases, XML modification will not work, and you have to resort to app code on Kotlin or JavaThe approach depends on which button class you are using: standard Button or MaterialButton.
For a standard Android widget, the setBackgroundTintList() method allows you to change the background tint at runtime. However, if you are working with a MaterialButton, you have more. specific methods such as setBackgroundColor() or setStrokeColor(). It is important to remember about data types: methods usually expect an object ColorStateList or an integer color value (Int) obtained via ContextCompat.getColor().
Kotlin code example for changing color:
val button = findViewById<MaterialButton>(R.id.myButton)// Changing the background color
button.backgroundTintList = ContextCompat.getColorStateList(this, R.color.green)
// Changing the text color
button.setTextColor(ContextCompat.getColor(this, R.color.white))
// Changing the outline color
button.strokeColor = ContextCompat.getColorStateList(this, R.color.dark_green)
When changing colors dynamically, make sure you handle configuration changes such as screen rotation or theme switching. If you hardcode the color in code, it may not update automatically when you change the theme. systems, as opposed to colors bound to resources via XML.
Why doesn't setBackground work as expected?
The setBackground method completely replaces the background Drawable. If you pass just a ColorDrawable there, you will lose the fillets and ripple effect. Use backgroundTintList to preserve the standard Material Design behavior.
Creating custom shapes and gradients
Standard rectangular buttons with one solid color are not suitable for every design. If your application requires a button with a gradient, a complex shape (for example, oval or with cut corners) or a shadow, you will have to create your own drawable resource. This is done using XML files in the folder. res/drawable.
To create a gradient, use the tag <gradient> inside the shape file. You can customize the direction (linear, radial), start and end colors, as well as the angle. After creating such a drawable file, it can be set as the background of the button. However, as mentioned earlier, this disables the standard ripple effect, so it is recommended to wrap your gradient in <ripple> (for API 21+) or use special compatible wrappers.
An example of creating a gradient background:
<shape xmlns:android="http://schemas.android.com/apk/res/android"><gradient
android:angle="45"
android:startColor="#FF512F"
android:endColor="#DD2476"
android:type="linear" />
<corners android:radius="16dp" />
</shape>
When using custom drawables, make sure you take into account different screen densities and Android versions. Gradients may look different on older devices. It is also worth testing the readability of the text against such a background, since the contrast of the gradient changes over the area of โโthe button.
โ ๏ธ Attention: When using custom drawables as a background, standard theme attributes (for example, colorPrimary) no longer affect the button. You take full responsibility for its appearance in different themes (light and dark).
Styling buttons in Jetpack Compose
Modern development on Android is increasingly moving to declarative UI using Jetpack Compose. Here the approach to styling is radically different from classic XML. Instead of changing the attributes of a specific widget, you pass parameters to the compose function or use modifiers.
In Compose, the main component is Button, which takes a parameter colors. Through the object ButtonDefaults.buttonColors() you can set the colors of the background, content (text/icon) and Disabled state. This allows you to create type-safe and easy-to-read style configurations right in Kotlin code.
Example of a button with a custom color in Compose:
Button(onClick = { / Action / },
colors = ButtonDefaults.buttonColors(
containerColor = Color(0xFF6200EE),
contentColor = Color.White
)
) {
Text("Click me")
}
Compose also integrates well with the theme system Material3. You can use semantic colors such as MaterialTheme.colorScheme.primaryto make the button automatically adapt to the current device theme. This eliminates the need to manually write hex codes and makes the code more resistant to design changes.
โ๏ธ Checklist before launch
Common errors and ways to solve them
Even experienced developers sometimes make mistakes when working with interface colors. One of the most common problems is ignoring status disabled. A button that becomes inactive must be visually different from the active one, otherwise the user will not understand why the click does not work. Make sure you adjust the colors for this state as well.
Another common mistake is using too bright or โacidโ colors that are not provided by the Material Design palette. This can make the application look cheap or unprofessional. Use the Accessibility tools built into Android Studio to make sure your colors meet WCAG contrast standards.
- ๐ซ Ignoring Dark Mode: A color that looks great during the day may be blinding to the user at night. Always check the layout in a dark theme.
- ๐ซ Hardcoding in the code: Avoid inserting magic color numbers directly into the Activity or Fragment logic.
- ๐ซ Loss of Ripple: Replacing the background without saving Ripple effect masks make the interface โdeadโ and non-interactive.
If you are faced with the fact that the button color does not change, check the style hierarchy. It's possible that the style applied in the app's theme takes precedence over the attributes set in the layout. In such cases, use the Layout Inspector tools in Android Studio to analyze applied styles in real time.
Getting button color right is a balance between aesthetics, accessibility, and technical implementation through resources, rather than hard-coding values.
FAQ: Frequently Asked Questions
How to make a transparent button with a colored frame?
For this it is best to use MaterialButton. Set the attribute app:backgroundTint to the value @android:color/transparent (or #00000000), and then set the desired color and thickness via app:strokeColor and app:strokeWidth. This will create the effect of an outline button.
Why does android:background not change the color, but only put the picture?
The attribute android:background expects Drawable. If you pass a color there, it will be converted to a ColorDrawable, but this may conflict with standard styles. To change the tint of a standard button, always use android:backgroundTint or app:backgroundTint.
Is it possible to change the color only when clicked?
Yes, for this you need to create a resource file of type color (ColorStateList) in the folder res/color. In it, you describe which color to use for the state state_pressedand which for the normal state, and reference this file in the tint attribute.
How to change the color of a button in Jetpack Compose globally?
In Jetpack Compose this is done through providing MaterialTheme. You can override colorScheme or create a custom one ButtonColors and pass it to the composition structure, or use LocalButtonColors to change the default values in a specific branch of the UI.
Does button color affect application performance?
The color itself (hex code or resource) does not affect performance. However, using complex gradients as a background for a large number of lists or frequently redrawing custom drawables in an animation loop can increase GPU load. For regular buttons, this is not a problem.