Kahibaro
Discord Login Register

24.2 Material Components

Understanding Material Components in Android

Material Components are a set of UI widgets and behaviors that follow Material Design guidelines. They are provided by the com.google.android.material library and extend or replace many of the standard Android views with versions that support Material theming, animation, and accessibility out of the box.

This chapter focuses on how to use some of the most common Material Components in a traditional XML based Android app. You will see what is special about these components compared to basic widgets, how to add them to your project, and how to connect them with Material themes. You will not learn the overall theory of Material Design here, only how to work with the concrete components.

Always pair Material Components with a MaterialComponents theme. Using Material widgets with a non Material theme often leads to crashes or broken UI.

Adding Material Components to Your Project

To use Material Components you need the Material library dependency in your app module build.gradle file. In a typical modern project this is already present in the template. If not, you add it manually.

dependencies {
    implementation "com.google.android.material:material:1.12.0"
}

After you sync Gradle, you get access to views in the com.google.android.material package, such as MaterialButton, TextInputLayout, AppBarLayout, and many others.

Material Components assume that your app theme extends a Theme.Material3. or Theme.MaterialComponents. parent. For example:

<style name="Theme.MyApp" parent="Theme.Material3.Light.NoActionBar">
    <!-- Customize your Material theme colors, typography, and shapes here -->
</style>

If your app does not use such a parent, Material Components may not display correctly or may crash when applying Material attributes.

Material Toolbar and App Bar

The Material Toolbar is a replacement for the old native Toolbar. It integrates with Material theming and can host navigation icons, titles, menus, and action items.

In XML you typically place it at the top of your layout inside an AppBarLayout to get correct elevation and scrolling behavior.

<com.google.android.material.appbar.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/topAppBar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:title="Home"
        app:navigationIcon="@drawable/ic_menu"
        app:menu="@menu/top_app_bar_menu" />
</com.google.android.material.appbar.AppBarLayout>

In your Activity or Fragment you can set listeners for navigation and menu items.

val topAppBar = findViewById<MaterialToolbar>(R.id.topAppBar)
topAppBar.setNavigationOnClickListener {
    // Handle navigation icon click
}
topAppBar.setOnMenuItemClickListener { item ->
    when (item.itemId) {
        R.id.action_settings -> {
            // Handle settings click
            true
        }
        else -> false
    }
}

The AppBarLayout works together with scrollable content and CoordinatorLayout behaviors, which you will usually use when you want collapsing or scrolling app bars. Those advanced behaviors are handled in layouts with specific app:layout_scrollFlags attributes and are part of the broader app bar patterns.

Material Buttons

Material provides several button types that replace the default Button widget. The basic one is MaterialButton, and there are specialized variants like MaterialButtonToggleGroup and Material 3 button styles applied through themes.

A simple Material button in XML can look like this:

<com.google.android.material.button.MaterialButton
    android:id="@+id/primaryButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Continue"
    style="@style/Widget.Material3.Button.Filled" />

Instead of specifying style directly on each button, you usually let the theme decide button styles with attributes like materialButtonStyle or Material 3 specific button styles. When you use a Theme.Material3 parent, component styles such as filled, outlined, and text buttons are defined and can be applied with style references.

Buttons behave like normal views for click listeners. In code:

val button = findViewById<MaterialButton>(R.id.primaryButton)
button.setOnClickListener {
    // Handle click
}

Material buttons support icons with attributes such as app:icon, app:iconPadding, and app:iconGravity.

<com.google.android.material.button.MaterialButton
    android:id="@+id/iconButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Favorite"
    app:icon="@drawable/ic_favorite"
    app:iconGravity="textStart"
    app:iconPadding="8dp" />

You can also place several MaterialButton views inside a MaterialButtonToggleGroup to create a group of mutually exclusive or multi select options, controlled with app:singleSelection or app:selectionRequired.

Text Fields with TextInputLayout and TextInputEditText

For text input, Material Components introduce TextInputLayout around an inner TextInputEditText. This combination provides features like floating labels, helper text, and error messages.

A typical Material text field in XML looks like this:

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/usernameLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Username"
    app:helperText="Use 4 to 20 characters">
    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/usernameInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>

The TextInputLayout handles the label, underline, helper text, and error display. You use the edit text like a regular EditText. In code you typically reference both:

val usernameLayout = findViewById<TextInputLayout>(R.id.usernameLayout)
val usernameInput = findViewById<TextInputEditText>(R.id.usernameInput)
val text = usernameInput.text?.toString().orEmpty()
if (text.length < 4) {
    usernameLayout.error = "Too short"
} else {
    usernameLayout.error = null
}

TextInputLayout also supports start and end icons such as a password visibility toggle or clear text icon. For example, for a password field:

<com.google.android.material.textfield.TextInputLayout
    android:id="@+id/passwordLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Password"
    app:endIconMode="password_toggle">
    <com.google.android.material.textfield.TextInputEditText
        android:id="@+id/passwordInput"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>

The endIconMode attribute automatically adds a clickable icon that toggles the visibility of the password text.

Always place TextInputEditText inside a TextInputLayout. Using a regular EditText inside TextInputLayout can break hints and styling.

Material Chips

Chips are compact elements that represent inputs, attributes, or actions. Material Components provide Chip and ChipGroup for this purpose.

A single chip:

<com.google.android.material.chip.Chip
    android:id="@+id/chipFilter"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Popular"
    style="@style/Widget.Material3.Chip.Filter" />

A group of chips that act like multiple choice filters:

<com.google.android.material.chip.ChipGroup
    android:id="@+id/chipGroupFilters"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:singleSelection="false">
    <com.google.android.material.chip.Chip
        android:id="@+id/chipNew"
        android:text="New"
        style="@style/Widget.Material3.Chip.Filter" />
    <com.google.android.material.chip.Chip
        android:id="@+id/chipSale"
        android:text="On sale"
        style="@style/Widget.Material3.Chip.Filter" />
</com.google.android.material.chip.ChipGroup>

You can make a chip checkable with android:checkable="true" or use predefined chip styles for choice, filter, or input chips. In code you can check which chips are selected by reading the checked chip ids from the group.

Material Cards with CardView and MaterialCardView

Material Components include MaterialCardView, which builds on the original CardView. It provides support for stroke, ripple, and checkable states controlled by Material attributes.

A basic card:

<com.google.android.material.card.MaterialCardView
    android:id="@+id/profileCard"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="16dp"
    app:cardCornerRadius="12dp"
    app:cardUseCompatPadding="true">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="16dp">
        <!-- Content inside the card -->
    </LinearLayout>
</com.google.android.material.card.MaterialCardView>

Material cards can be made checkable with app:checkable="true", and you can control the stroke color and width with app:strokeColor and app:strokeWidth.

Cards are commonly used in lists and grids for grouping content with elevation and rounded corners. They integrate visually with Material theming by inheriting surface colors and shapes from the theme.

Material Bottom Navigation and Navigation Bar

For navigation at the bottom of the screen, Material Components provide BottomNavigationView and, in Material 3, the NavigationBarView family. These views show icons and text for top level destinations.

A simple bottom navigation using BottomNavigationView looks like this:

<com.google.android.material.bottomnavigation.BottomNavigationView
    android:id="@+id/bottomNavigation"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="bottom"
    app:menu="@menu/bottom_nav_menu" />

The menu attribute references a menu resource that defines navigation items. Each item has an id, icon, and title. In code you handle item selection.

val bottomNavigation = findViewById<BottomNavigationView>(R.id.bottomNavigation)
bottomNavigation.setOnItemSelectedListener { item ->
    when (item.itemId) {
        R.id.nav_home -> {
            // Show home
            true
        }
        R.id.nav_search -> {
            // Show search
            true
        }
        else -> false
    }
}

When using the Navigation component, you can connect BottomNavigationView with a NavController to handle navigation automatically.

Material 3 adds NavigationBarView and styles that you apply through your theme or XML to achieve the updated design with rounded indicators.

Floating Action Button

The Floating Action Button (FAB) is a circular button that represents a primary action in the app. Material Components provide FloatingActionButton in one of the most common forms.

In XML:

<com.google.android.material.floatingactionbutton.FloatingActionButton
    android:id="@+id/fabAdd"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="end|bottom"
    android:layout_margin="16dp"
    app:srcCompat="@drawable/ic_add"
    app:tint="@color/white" />

You usually place the FAB in a CoordinatorLayout together with content, which allows it to respond to scrolling with default behaviors, such as hiding when the user scrolls down.

In code you use it like a regular button.

val fab = findViewById<FloatingActionButton>(R.id.fabAdd)
fab.setOnClickListener {
    // Perform main action
}

You can animate the FAB with simple calls, such as hide() and show(), which include Material friendly animations.

Material Snackbars

Although snackbars are covered in user interaction, Material Components provide the Snackbar implementation you usually use.

A snackbar is created and shown from code. You pass a view to attach it to, a message, and a duration.

Snackbar.make(
    findViewById(R.id.rootLayout),
    "Item deleted",
    Snackbar.LENGTH_LONG
).setAction("Undo") {
    // Restore item
}.show()

Material theming can customize snackbar background color, text color, and shape through theme attributes, so the snackbar looks consistent with the rest of your app.

Tabs with TabLayout

For organizing content into multiple pages, Material Components provide TabLayout. It is usually combined with ViewPager2 to swipe between pages.

In XML:

<com.google.android.material.tabs.TabLayout
    android:id="@+id/tabLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:tabMode="fixed"
    app:tabGravity="fill" />

Tabs can be added from code.

val tabLayout = findViewById<TabLayout>(R.id.tabLayout)
tabLayout.addTab(tabLayout.newTab().setText("First"))
tabLayout.addTab(tabLayout.newTab().setText("Second"))
tabLayout.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
    override fun onTabSelected(tab: TabLayout.Tab) {
        // Respond to tab selected
    }
    override fun onTabUnselected(tab: TabLayout.Tab) {}
    override fun onTabReselected(tab: TabLayout.Tab) {}
})

In a complete implementation, you connect TabLayout with ViewPager2 or switch fragments manually when the selected tab changes.

Material Dialogs

Material Components provide themes and styles for dialogs, and MaterialAlertDialogBuilder for constructing them. This builder wraps the usual AlertDialog API but applies Material styling and theming.

In an Activity or Fragment you can show a Material dialog like this:

MaterialAlertDialogBuilder(this)
    .setTitle("Delete item")
    .setMessage("Are you sure you want to delete this item?")
    .setNegativeButton("Cancel") { dialog, _ ->
        dialog.dismiss()
    }
    .setPositiveButton("Delete") { _, _ ->
        // Perform deletion
    }
    .show()

The appearance of the dialog is controlled by dialog theme attributes in your main theme or with a specific theme overlay.

Material Sliders and Progress Indicators

Material Components include modern sliders and progress indicators that fit Material guidelines.

A continuous slider:

<com.google.android.material.slider.Slider
    android:id="@+id/volumeSlider"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:valueFrom="0"
    android:valueTo="100"
    android:value="50" />

In code you handle value changes.

val slider = findViewById<Slider>(R.id.volumeSlider)
slider.addOnChangeListener { _, value, fromUser ->
    if (fromUser) {
        // Use new value
    }
}

Material progress indicators come as circular and linear variants.

Linear indeterminate indicator:

<com.google.android.material.progressindicator.LinearProgressIndicator
    android:id="@+id/loadingIndicator"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:indeterminate="true" />

In code you show or hide them by setting visibility or toggling isIndeterminate or setProgress for determinate mode.

Theme Overlays and Component Customization

Material Components rely heavily on themes to define their colors, typography, and shapes. Besides the main app theme, you can apply a theme overlay to specific views to change their appearance without modifying the entire app.

For example, a special toolbar style:

<com.google.android.material.appbar.MaterialToolbar
    android:id="@+id/topAppBar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:theme="@style/ThemeOverlay.MyApp.TopAppBar" />

Then in styles.xml:

<style name="ThemeOverlay.MyApp.TopAppBar" parent="ThemeOverlay.Material3.Dark.ActionBar">
    <!-- Customize toolbar colors and typography -->
</style>

You can also use component specific attributes like shapeAppearance, shapeAppearanceOverlay, or color attributes such as backgroundTint to fine tune individual components.

Prefer theme attributes over hard coded colors and styles for Material Components. This keeps your UI consistent, supports dark mode, and simplifies changes later.

Material Components are designed to work together. By combining a Material theme, AppBar, bottom navigation, FAB, cards, and text fields, you can build interfaces that look modern and behave consistently across Android versions with minimal custom work.

Views: 1

Comments

Please login to add a comment.

Don't have an account? Register now!