A Complete Guide to Material Components for Android Developers

Material Components for Android (MDC-Android) represent the official implementation of Google’s Material Design system, offering a comprehensive library of UI components, theming tools, and interaction patterns. This guide provides a deep, actionable exploration of MDC-Android, from core concepts to advanced customization, ensuring developers can build polished, consistent, and accessible applications.
Core Architecture and Theming
MDC-Android is built on a robust theming architecture that replaces the older AppCompat system. The foundational element is the MaterialThemeOverlay, which applies Material attributes to child views automatically. The theme chain begins with your app’s Application theme, which should inherit from a Material parent theme like Theme.Material3.DayNight.NoActionBar.
Key Theming Components:
ColorRoles: Defines primary, secondary, tertiary, error, and surface colors.Typography: Manages text appearance through a type scale (Display, Headline, Title, Body, Label).Shape: Controls corner radii viaShapeAppearanceModelfor small, medium, and large components.
To implement custom theming, use XML attributes in themes.xml:
@color/my_primary
@color/my_secondary
@style/MyHeadlineLarge
Programmatic theming is possible via MaterialTheme in Compose, but for XML-based layouts, the MaterialThemeOverlay ensures nested components inherit correctly. Always test your color contrast using the Material Design color tool to meet WCAG accessibility standards.
Essential Components and Their Usage
Buttons and FABs
Material offers distinct button variants. MaterialButton replaces AppCompatButton and supports style="@style/Widget.Material3.Button" for filled, Button.Tonal for tonal, and Button.OutlinedButton for outlined styles. The MaterialButtonToggleGroup provides radio-button-like selection for grouped actions.
Floating Action Button (FAB):
- Use
com.google.android.material.floatingactionbutton.FloatingActionButton - Supporting three sizes:
FAB_SIZE_NORMAL,FAB_SIZE_MINI, andFAB_SIZE_AUTO - Animated transformation to
ExtendedFloatingActionButtonviashrink()andextend()methods
Text Fields and Input
TextInputLayout remains the cornerstone for user input. It encapsulates TextInputEditText and provides:
setEndIconMode()for password toggle, clear text, or custom icons- Error display via
setError()andsetErrorIconDrawable() setHelperText()for supplementary information
Material 3 introduces OutlinedTextField with boxStrokeColor that adapts to focus states. For complex forms, implement TextInputLayout with app:endIconMode="password_toggle" and validate input using addTextChangedListener.
Cards and Surfaces
MaterialCardView extends CardView with Material theming. Key attributes include:
app:strokeColorandapp:strokeWidthfor outlined cardsapp:cardForegroundColorfor ripple effects on clickable cardssetChecked()for selectable cards in grid layouts
For a unified container, MaterialShapeDrawable programmatically creates surfaces with custom shape and elevation. Use ViewOutlineProvider to clip views to rounded rectangles without a Card wrapper.
Bottom Navigation and Tabs
BottomNavigationView now uses menu items with app:menu and supports itemIconTint and itemTextColor via selectors. Material 3 introduces NavigationBarView for bottom bars and NavigationRailView for side navigation on tablets.
TabLayout integrates with ViewPager2 using TabLayoutMediator. Call TabLayoutMediator(tabLayout, viewPager2) { tab, position -> tab.text = items[position].title }.attach() to synchronize tabs. Custom tab views are possible via setCustomView().
Advanced Customization and Animations
Shape and Elevation
The ShapeAppearanceModel class allows per-corner radii control. Example for a pill-shaped button:
val shape = ShapeAppearanceModel.builder()
.setAllCornerSizes(ShapeAppearanceModel.PILL)
.build()
materialButton.shapeAppearanceModel = shapeElevation supports dynamic change with setElevation(), but for animated transitions, use MotionLayout keyframes or TransitionManager.beginDelayedTransition() on a MotionScene.
Motion and Transitions
Material components integrate with AndroidX Transitions. The MaterialContainerTransform provides shared element transitions between fragments. Implement MaterialSharedAxis for list-to-detail animations:
val transform = MaterialContainerTransform()
transform.duration = 300L
TransitionManager.beginDelayedTransition(container, transform)For micro-interactions, MaterialElevationOverlay uses elevationOverlayProvider to apply overlay color on elevation change, visible on dark themes.
Dark Theme and Dynamic Colors
MDC-Android fully supports DayNight themes. Enable dynamic color on Android 12+ with android:colorMode="wideColorGamut" and Monet palettes. In XML:
@color/m3_dynamic_primary
For programmatic dynamic color, use DynamicColors.applyToActivityIfAvailable(activity) in your Application.onCreate().
Accessibility and Testing
Material components are built with accessibility in mind. MaterialButton automatically sets contentDescription from text. Ensure custom components use importantForAccessibility and accessibilityTraversalAfter. Test with TalkBack:
- Validate focus order for
TabLayoutandBottomNavigationView - Confirm
TextInputLayouterror announcements - Check
MaterialCardViewclickable vs. non-clickable states
Unit test component states using Robolectric with Material themes:
@RunWith(RobolectricTestRunner::class)
@Config(theme = "Theme.Material3.DayNight")
fun testButtonClick() {
val button = MaterialButton(context).apply { text = "Submit" }
button.performClick()
// assert navigation or state change
}Espresso tests should use onView(withId(R.id.button)).check(matches(isDisplayed())) and test ripple feedback with hasBackground() matcher.
Performance Optimization
Material components can impact performance if misused. Follow these practices:
- Use
ViewStubfor rarely visible components (e.g., bottom sheets) - Avoid nesting
MaterialCardViewinsideRecyclerViewitems; useMaterialShapeDrawableon aConstraintLayout - For
RecyclerView, implementDiffUtilsnapshots to minimize layout passes - Set
app:elevation="0dp"on static lists and useStateListAnimatorfor press feedback without GPU overdraw
For TabLayout with many tabs, enable TabLayoutMediator with autoRefresh = false and call forceLayout() only on configuration changes.
Migration from AppCompat
If migrating an existing AppCompat app, follow a gradual process:
- Update
build.gradletocom.google.android.material:material:1.12.0 - Replace
AppCompatActivitywithMaterialCompatActivity - Change button
stylefrom@style/Widget.AppCompat.Buttonto@style/Widget.Material3.Button - Replace
CardViewwithMaterialCardView - Update
TextInputLayoutto useapp:endIconModeinstead of manual toggle
Test each component incrementally; the MaterialThemeOverlay will apply default Material styles without breaking existing layouts. Use Android Studio’s refactoring tool for bulk replacements.
Integration with Jetpack Compose
MDC-Android and Jetpack Compose share the Material Design system but differ in implementation. For hybrid apps, use AndroidView to embed Material views in Compose:
@Composable
fun MaterialButtonInCompose() {
AndroidView(factory = { ctx ->
MaterialButton(ctx).apply {
text = "Hybrid Button"
setOnClickListener { /* action */ }
}
})
}For theming parity, define a MaterialTheme in Compose that reads Material3 colors from the XML theme using LocalContext.current.theme. Avoid mixing Material3 and Material2 components in the same screen.
Troubleshooting Common Issues
Problem: Tonal buttons show incorrect background color.
Fix: Ensure colorSecondaryContainer is defined in your theme. Use app:backgroundTint="@color/my_tonal_color" for explicit control.
Problem: TextInputLayout error icon overlaps with end icon.
Fix: Set app:endIconMode="none" when calling setError(), or use setErrorIconDrawable(null).
Problem: BottomNavigationView menu items not reflecting selected state.
Fix: Check menu XML for android:checkable="true" and call setSelectedItemId() after adapter initialization.
Problem: Elevation animation jank on MaterialCardView.
Fix: Override setElevation() with animate().elevation() or use ViewPropertyAnimator with hardware acceleration.
Resources and Continuous Learning
Google publishes the Material Design guidelines at m3.material.io, with component specification updates. The MDC-Android repository on GitHub provides sample code and issue tracking. Android Studio’s layout editor includes Material component palettes for drag-and-drop prototyping. Join the Material Design community Discord for real-time support.
Automated accessibility testing with AccessibilityScanner and visual regression tools like Shot can catch regressions. For animation performance, use Systrace and GPU Profiling in developer options to identify overdraw.
The ecosystem evolves with each Android release; follow the Android Developers Blog and Material Design Medium publication for updates on new components like SearchBar, SideSheet, and NavigationSuite. By mastering MDC-Android, developers ensure their apps deliver a cohesive, delightful User Experience aligned with modern platform standards.





