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

ComponentWhat It's For
MaterialButtonA Material-styled button — filled, outlined, or text style — replacing the plain Button widget.
TextInputLayout + TextInputEditTextA 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.
FloatingActionButtonA circular, elevated button reserved for a screen's single most important action.
MaterialCardViewA Material-styled card with proper elevation, corner radius, and stroke support.
BottomNavigationViewA 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;
}
Explanation: setError() draws the message in red beneath the field and outlines the box in the error color, entirely built in — no separate error TextView needed. Passing null once the field becomes valid clears that state again.

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);
});
Explanation: The FAB's OnClickListener is a plain click listener, same as any other View — the "Material" part is purely the circular, elevated look Material Components draws for you, plus its ripple and default shadow.
Up next: Resources Overview looks at where values like @color/recipe_green and @string/app_name, seen throughout this lesson, actually live.