If the "wrap" overflow mode is in use, the button group will wrap the buttons that don't fit in one row to more rows below. PiperOrigin-RevId: 800551513
21 KiB
Button groups
Button groups organize buttons and add interactions between them.There are two variants of a button group.
- Standard button group
- Connected button group
Note: Images use various dynamic color schemes.
Design & API documentation
Anatomy
Button groups are invisible containers that add padding between buttons and modify button shape. They don’t contain any buttons by default.
- Container
More details on anatomy items in the component guidelines.
M3 Expressive
M3 Expressive update
Before you can use Material3Expressive component styles, follow the
Material3Expressive themes setup instructions.
Button groups apply shape, motion, and width changes to buttons and icon buttons to make them more interactive. More on M3 Expressive
Button groups are new components added in Expressive.
Types and naming:
- Added standard button group
- Added connected button group
- Use instead of segmented button, which is deprecated
Configurations:
- Works with all button sizes: XS, S, M, L, and XL
- Applies default shape to all buttons: round or square
M3 Expressive styles
Default styles in the expressive themes:
- Standard button group:
Widget.Material3Expressive.MaterialButtonGroup - Connected button group:
Widget.Material3Expressive.MaterialButtonGroup.Connected
Key properties
Shape and size attributes
| Element | Attribute | Related method(s) | Default value |
|---|---|---|---|
| Group shape (outer corners) | app:shapeAppearance |
setShapeAppearancegetShapeAppearance |
none |
| Size of inner corners | app:innerCornerSize |
setInnerCornerSizegetInnerCornerSize |
none |
| Spacing between buttons | android:spacing |
setSpacinggetSpacing |
12dp |
| Child size change | app:childSizeChange |
N/A | 15% in pressed,otherwise, 0% |
| Child overflow mode | app:overflowMode |
setOverflowModegetOverflowMode |
none |
| Overflow button icon | app:overflowButtonIcon |
setOverflowButtonIcon |
abc_ic_menu_overflow_material (3 dots) |
Additional attributes of child buttons
| Element | Attribute | Related method(s) | Default value |
|---|---|---|---|
| Title of the overflow menu item | app:layout_overflowText |
N/A | button's text value, if not specified or empty |
| Icon of the overflow menu item | app:layout_overflowIcon |
N/A | null |
Styles and theme attributes
| Element | Style | Theme Attribute |
|---|---|---|
| Default style | Widget.Material3.MaterialButtonGroup |
?attr/materialButtonGroupStyle |
| Overflow icon button style | ?attr/materialIconButtonStyle |
?attr/materialButtonGroupOverflowButtonStyle |
| Overflow menu style | ?attr/popupMenuStyle |
?attr/materialButtonGroupOverflowPopupMenuStyle |
Variants of button groups
Standard button group
The standard button group contains multiple related individual buttons. The individual button's shape is preserved.
Button group examples
Source code:
MaterialButtonGroupMaterialButton
The following example shows a button group with three buttons that have text labels.
In the layout:
<com.google.android.material.button.MaterialButtonGroup
android:id="@+id/buttonGroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1"
/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2"
/>
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 3"
/>
</com.google.android.material.button.MaterialButtonGroup>
Connected button group
In addition to standard button groups, connected button group also overrides the individual button's shape to make them visually more belong to a group with 2dp spacing, 8dp inner corners, and fully rounded outer corners.
Connected button group examples
Source code:
MaterialButtonGroupMaterialButton
The following example shows a connected button group with three buttons that have text labels. To correctly style a button group as connected button group, the specific style needs to be set.
In the layout:
<com.google.android.material.button.MaterialButtonGroup
android:id="@+id/buttonGroup"
style="@style/Widget.Material3.MaterialButtonGroup.Connected"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<Button
style="?attr/materialButtonOutlinedStyle"
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 1" />
<Button
style="?attr/materialButtonOutlinedStyle"
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 2" />
<Button
style="?attr/materialButtonOutlinedStyle"
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button 3" />
</com.google.android.material.button.MaterialButtonGroup>
Code implementation
Before you can use Material button groups, you need to add a dependency to the Material components for Android library. For more information, go to the Getting started page.
Note: <Button> is auto-inflated as
<com.google.android.material.button.MaterialButton> via
MaterialComponentsViewInflater when using a Theme.Material3.* theme.
Making button groups adaptive
MaterialButtonGroup inherits from the LinearLayout. It can be configured to
achieve different child arrangements for different screen sizes or foldable
screens by using layout_width and layout_weight.
Fixed button sizes
When child buttons should not be adjusted while screen size changes, consider
using layout_width on all buttons.
<com.google.android.material.button.MaterialButtonGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:gravity="center_horizontal"
android:spacing="4dp">
<Button
style="?attr/materialIconButtonFilledStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/cat_button_previous_icon"
android:gravity="center"
app:iconGravity="textStart"
app:icon="@drawable/cat_button_previous_icon"/>
<Button
style="?attr/materialIconButtonFilledStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/cat_button_play_icon"
android:gravity="center"
app:iconGravity="textStart"
app:icon="@drawable/cat_button_play_icon"/>
<Button
style="?attr/materialIconButtonFilledStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/cat_button_next_icon"
android:gravity="center"
app:iconGravity="textStart"
app:icon="@drawable/cat_button_next_icon"/>
</com.google.android.material.button.MaterialButtonGroup>
Flexible button sizes
When all child buttons are equally important or their sizes are proportional to
each other, consider using layout_weight on all buttons.
<com.google.android.material.button.MaterialButtonGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:gravity="center_horizontal"
android:spacing="4dp">
<Button
style="?attr/materialIconButtonFilledStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/cat_button_previous_icon"
android:gravity="center"
app:iconGravity="textStart"
app:icon="@drawable/cat_button_previous_icon"/>
<Button
style="?attr/materialIconButtonFilledStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:contentDescription="@string/cat_button_play_icon"
android:gravity="center"
app:iconGravity="textStart"
app:icon="@drawable/cat_button_play_icon"/>
<Button
style="?attr/materialIconButtonFilledStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@string/cat_button_next_icon"
android:gravity="center"
app:iconGravity="textStart"
app:icon="@drawable/cat_button_next_icon"/>
</com.google.android.material.button.MaterialButtonGroup>
Mixed button sizes
When only some buttons are flexible for different screen sizes, consider using
layout_weight on these buttons but use layout_width on the rest as below.
<com.google.android.material.button.MaterialButtonGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:gravity="center_horizontal"
android:spacing="4dp">
<Button
style="?attr/materialIconButtonFilledStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/cat_button_previous_icon"
android:gravity="center"
app:iconGravity="textStart"
app:icon="@drawable/cat_button_previous_icon"/>
<Button
style="?attr/materialIconButtonFilledStyle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:contentDescription="@string/cat_button_play_icon"
android:gravity="center"
app:iconGravity="textStart"
app:icon="@drawable/cat_button_play_icon"/>
<Button
style="?attr/materialIconButtonFilledStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/cat_button_next_icon"
android:gravity="center"
app:iconGravity="textStart"
app:icon="@drawable/cat_button_next_icon"/>
</com.google.android.material.button.MaterialButtonGroup>
Handling overflow
Overflow happens when the screen size or button group size is not enough to
display all child buttons. By default (mode none), the button's text will be
clipped or wrapped.
Overflow mode - menu
Setting overflowMode=menu dynamically hides child buttons that don't fit in
the current screen width in a popup menu. An icon button will be added
automatically at the end of the button group for toggling the popup menu, once
it's needed. The style of this icon button can be set via
materialButtonGroupOverflowButtonStyle attribute in your theme overlay. The
icon can be configured via overflowButtonIcon in the button group.
Every hidden child button will be represented by a MenuItem in the popup menu.
You can specify the menu item's title via layout_overflowText and the menu
item's icon via layout_overflowIcon in the specific button.
Note: Do not use the menu overflow mode to toggle button group, since the
toggle button group should demonstrate all available options and the current
selection.
Note: This feature assumes all child buttons should be visible in the group
or as a menu item in the overflow menu. Visibility of all child buttons will be
managed by the button group when setting overflowMode=menu.
Overflow mode - wrap
Setting overflowMode=wrap will cause the buttons to wrap to the next line when
they don't fit on the current line. This can be useful when you want to display
all buttons without hiding them in a menu, but you have a limited amount of
horizontal space. The buttons will maintain their shape and size as defined in
the layout.
This mode is useful in cases:
- Responsive layouts: When you want buttons to adapt to different screen sizes by wrapping to the next line instead of being hidden.
- Content-heavy interfaces: When you have many buttons and want to ensure they are all visible, even on smaller screens.
- Accessibility: When you need to display all buttons but there's not enough space.
Configuration
Do not use the wrap overflow mode with layout_width="wrap_content",
orientation="vertical", or layout_weight in child buttons, due to undefined
expected behaviors. The layout_width can be set to a fixed dp size or
match_parent. The height of the group is determined by the number of wrapped
rows and spacing. So the value of layout_height will be ignored.
Wrapping gravity
In order to make the child buttons wrapped to the correct position, they must
have layout_gravity set. When start|top is used, the android:gravity in
MaterialButtonGroup can be ignored. If end|top is used, the
android:gravity in MaterialButtonGroup must be set to end as well.
Making buttons accessible
Buttons support content labeling for accessibility and are readable by most screen readers, such as TalkBack. Text rendered in buttons is automatically provided to accessibility services. Additional content labels are usually unnecessary.
For more information on content labels, go to the Android accessibility help guide.
Customizing button groups
Theming buttons
Buttons support the customization of color, typography, and shape.
Button theming example
API and source code:
MaterialButton
The following example shows text, outlined and filled button types with Material theming.
Implementing button theming
Use theme attributes and styles in res/values/styles.xml to add the theme to
all buttons. This affects other components:
<style name="Theme.App" parent="Theme.Material3.*">
...
<item name="colorPrimary">@color/shrine_pink_100</item>
<item name="colorOnPrimary">@color/shrine_pink_900</item>
<item name="textAppearanceLabelLarge">@style/TextAppearance.App.Button</item>
<item name="shapeCornerFamily">cut</item>
</style>
<style name="TextAppearance.App.Button" parent="TextAppearance.Material3.LabelLarge">
<item name="fontFamily">@font/rubik</item>
<item name="android:fontFamily">@font/rubik</item>
</style>
Use default style theme attributes, styles and theme overlays. This adds the theme to all buttons but does not affect other components:
<style name="Theme.App" parent="Theme.Material3.*">
...
<item name="borderlessButtonStyle">@style/Widget.App.Button.TextButton</item>
<item name="materialButtonOutlinedStyle">@style/Widget.App.Button.OutlinedButton</item>
<item name="materialButtonStyle">@style/Widget.App.Button</item>
</style>
<style name="Widget.App.Button.TextButton" parent="Widget.Material3.Button.TextButton">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Button.TextButton</item>
<item name="android:textAppearance">@style/TextAppearance.App.Button</item>
<item name="shapeAppearance">@style/ShapeAppearance.App.Button</item>
</style>
<style name="Widget.App.Button.OutlinedButton" parent="Widget.Material3.Button.OutlinedButton">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Button.TextButton</item>
<item name="android:textAppearance">@style/TextAppearance.App.Button</item>
<item name="shapeAppearance">@style/ShapeAppearance.App.Button</item>
</style>
<style name="Widget.App.Button" parent="Widget.Material3.Button">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Button</item>
<item name="android:textAppearance">@style/TextAppearance.App.Button</item>
<item name="shapeAppearance">@style/ShapeAppearance.App.Button</item>
</style>
<style name="ThemeOverlay.App.Button.TextButton" parent="ThemeOverlay.Material3.Button.TextButton">
<item name="colorOnContainer">@color/shrine_pink_900</item>
</style>
<style name="ThemeOverlay.App.Button" parent="ThemeOverlay.Material3.Button">
<item name="colorContainer">@color/shrine_pink_100</item>
<item name="colorOnContainer">@color/shrine_pink_900</item>
</style>
<style name="ShapeAppearance.App.Button" parent="">
<item name="cornerFamily">cut</item>
<item name="cornerSize">4dp</item>
</style>
Use one of the styles in the layout. That will affect only this button:
<Button style="@style/Widget.App.Button".../>
Optical centering
Optical centering means to offset the MaterialButton’s contents (icon and/or
label) when the shape is asymmetric. Before optical centering, we only provided
centering with horizontally asymmetrical shapes.
To turn on optical centering for a given button, use
setOpticalCenterEnabled(true). Optical centering is disabled by default. When
enabled, the shift amount of the icon and/or text is calculated as a value with
the fixed ratio to the difference between left corner size in dp and right
corner size in dp. The shift amount is applied to the padding start and padding
end.









