How to change the color of a CheckBox in Android
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Changing a CheckBox color in Android looks simple, but color often appears wrong when theme overlays, disabled state, and API differences are not handled together. A robust solution should define colors for checked, unchecked, and disabled states, then apply them in a way that survives activity restarts and theme changes. This guide shows a practical approach using XML tint resources and Kotlin code.
Understand What You Are Coloring
In Android, a CheckBox has two visual pieces: the box icon and the text label. Most color questions are about the box icon. If you only set text color, the check indicator can still use the default theme color, which makes the UI inconsistent.
The most reliable strategy is:
- Use a stateful color resource for the indicator.
- Apply it with
android:buttonTintorapp:buttonTint. - Keep label color separate using
android:textColor.
When you treat these parts independently, your control remains readable in both light and dark themes.
Define a Stateful Color List in XML
A stateful color list keeps behavior predictable. The order of items matters, so put the most specific states first and the fallback last.
Then use it in layout.
Use AppCompatCheckBox when possible because support behavior is more consistent across Android versions.
Apply and Update Color Programmatically in Kotlin
If you need runtime theming or a user selected accent color, apply tint in Kotlin. The following example can run in an Activity and updates both initial state and dynamic changes.
This approach is useful when the color source comes from remote config or user preferences.
Support Older Devices with a Custom Button Drawable
On older projects, tint behavior can be inconsistent if theme setup is incomplete. A fallback is using a custom state list drawable assigned to android:button. That gives full control over checked and unchecked assets.
This method requires maintaining two drawable assets, but it is deterministic and easy to verify visually.
Common Pitfalls
- Coloring only one state. If disabled and unchecked colors are missing, Android falls back to theme defaults and visual contrast can break.
- Using
android:buttonTintwith plainCheckBoxin a setup that expectsapp:buttonTint. Mixed widget families cause inconsistent rendering. - Forgetting dark theme testing. A color that looks clear in light mode can fail contrast checks in dark mode.
- Setting tint in code before the view is fully initialized in complex custom views. Apply after view inflation or in lifecycle safe points.
- Treating text and indicator as one style target. Keep them separate so accessibility remains strong.
Summary
- Use a stateful color list to define checked, unchecked, and disabled behavior.
- Prefer
AppCompatCheckBoxplusapp:buttonTintfor consistent cross version behavior. - Apply tint programmatically when theme data changes at runtime.
- Use a custom button drawable fallback for strict legacy support.
- Validate in light theme, dark theme, and disabled state before release.

