Android - border for button
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Adding borders to Android buttons is usually done with drawable resources or Material component stroke attributes. The right method depends on whether your UI uses classic Button widgets or MaterialButton. A production-ready border style also handles pressed, disabled, and dark-theme states consistently.
Border With XML Shape Drawable
A straightforward approach is creating a drawable with transparent fill and stroke.
Create res/drawable/button_border.xml.
Apply in layout:
This works well for many legacy or simple layouts.
Preferred Material Approach
If your app uses Material Components, prefer MaterialButton stroke properties.
This integrates better with ripple, elevation, and theme overlays.
State-Aware Border Colors
Buttons should visually communicate pressed and disabled states. Use a color selector for stroke color.
Create res/color/button_stroke_selector.xml.
Then set app:strokeColor to this selector for MaterialButton.
Programmatic Border Updates
When theme or state changes dynamically, update border in Kotlin.
Use resource-driven values, not hardcoded pixels.
Dark Mode and Contrast
A border visible in light theme may disappear in dark theme. Define semantic colors for both modes and verify contrast with surrounding surfaces. Do not rely on one static hex value unless it is part of a controlled design token system.
Test outlined buttons in:
- light theme
- dark theme
- disabled state
- high contrast accessibility mode
Layout and Rendering Issues
If border appears clipped or missing, check:
- parent container clipping behavior
- button minimum height and padding
- background override from style or theme
- corner radius too large for button size
Small layout constraints can make stroke invisible even when drawable is correct.
Accessibility and UX Considerations
Border should not be the only indicator of state. Combine border changes with text color, elevation, or icon feedback. Ensure touch target still meets recommended size for usability. Outlined style should remain clear for users with low vision.
Reusable Design System Styles
Instead of one-off border drawables per screen, define reusable button styles in themes. This keeps border width, radius, and color behavior consistent across app modules.
A centralized style also makes redesign and theme updates safer because one change propagates predictably.
Quick Verification Checklist
Before shipping, verify outlined buttons on multiple devices and densities. Check pressed, focused, and disabled states in both light and dark themes. Confirm border remains visible when dynamic text size increases and when localization expands button label length.
Common Pitfalls
A common pitfall is mixing custom drawable backgrounds with Material styles and losing expected ripple behavior. Another is forgetting disabled and pressed state border definitions. Teams often hardcode color values and break dark-mode contrast. Border clipping from tight layout constraints is also frequent. Finally, accessibility is overlooked when border is treated as the only state cue.
Summary
- Use shape drawables for classic buttons and simple border needs.
- Prefer
MaterialButtonstroke APIs in Material-based apps. - Define state-aware border colors for pressed and disabled behavior.
- Validate border visibility across light and dark themes.
- Use reusable style definitions for consistent UI.
- Pair border styling with accessibility-friendly state feedback.

