Material Components
The Material Components for Android library (the com.google.android.material dependency) is Google's own official implementation of the Material Design system — the buttons, text fields, cards, and navigation bars that give a modern Android app its familiar, polished feel, instead of hand-rolling equivalent behavior from plain Views. This lesson tours the components RecipeBox leans on most, and builds its "add recipe" form as a full worked example.
Commonly Used Material Components
| Component | What It's For |
|---|---|
| MaterialButton | A Material-styled button — filled, outlined, or text style — replacing the plain Button widget. |
| TextInputLayout + TextInputEditText | A text field with a floating label that animates above the input as the user types, plus built-in support for an error message shown beneath the field. |
| FloatingActionButton | A circular, elevated button reserved for a screen's single most important action. |
| MaterialCardView | A Material-styled card with proper elevation, corner radius, and stroke support. |
| BottomNavigationView | A row of destinations pinned to the bottom of the screen, for switching between a small number of top-level sections. |
Worked Example: RecipeBox's Add-Recipe Form
RecipeBox's "add recipe" screen uses TextInputLayout wrapped around a TextInputEditText for the recipe title:
<!-- res/layout/fragment_add_recipe.xml (excerpt) -->
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/titleInputLayout"
android:hint="Recipe title"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/titleEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
android:hint on the TextInputLayout itself (not the inner EditText) is what becomes the floating label. Validating the field and showing an error uses a single property on the layout:
// AddRecipeFragment.java
private boolean validateTitle() {
String title = titleEditText.getText() == null ? "" : titleEditText.getText().toString().trim();
if (title.isEmpty()) {
titleInputLayout.setError("Title is required");
return false;
}
titleInputLayout.setError(null); // clear any previous error
return true;
}
The Required Base Theme
Material Components have one real, common beginner gotcha: they need the app's theme (in res/values/themes.xml) to descend from a Material theme, or they render broken and unstyled — flat, colorless, missing the elevation and ripple effects that define the design language:
<!-- res/values/themes.xml -->
<style name="Theme.RecipeBox" parent="Theme.Material3.DayNight.NoActionBar">
<item name="colorPrimary">@color/recipe_green</item>
</style>
Theme.Material3.DayNight (or the older Theme.MaterialComponents family) is a required base, not an optional nicety. If a MaterialButton or TextInputLayout in RecipeBox ever looks plain, square, or oddly colored, the first thing to check is whether the app's theme actually extends a Material parent rather than a plain Theme.AppCompat one.
Worked Example: The FloatingActionButton
RecipeBox's recipe-list screen anchors a FloatingActionButton to its bottom-right corner, launching the "add recipe" screen:
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/addRecipeFab"
android:contentDescription="Add recipe"
app:srcCompat="@drawable/ic_add"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
// RecipeListActivity.java
FloatingActionButton addRecipeFab = findViewById(R.id.addRecipeFab);
addRecipeFab.setOnClickListener(v -> {
Intent intent = new Intent(this, AddRecipeActivity.class);
startActivity(intent);
});