- Hands-on with Material Components for Android: Buttons
- Part 4 of a series covering practical usage of Material Components for Android
- Setting up a Material Components theme for Android
- Attribute by attribute
- Basic usage 🏁
- Choosing a style 🤔
- Adding an icon 🔷
- Grouping Buttons to create a Toggle Button 👨👩👧👦
- Grouping
- Adjusting selected behavior
- Listening for selection state
- Orientation
- Theming 🎨
- Color
- Typography
- Shape
- More resources 📚
- [MaterialButton] Text misalignment with icon with viewStart alignment #1996
- Comments
- bmc08gt commented Jan 18, 2021 •
- bmc08gt commented Jan 18, 2021 •
- pekingme commented Jan 20, 2021
- bmc08gt commented Jan 20, 2021
- pekingme commented Jan 21, 2021
- Android materialbutton icon center
Hands-on with Material Components for Android: Buttons
Part 4 of a series covering practical usage of Material Components for Android
This post will be covering the features and API of Button components. To find out how to handle initial setup of Material Components for Android (including the Gradle dependency and creating an app theme), please see my original post:
Setting up a Material Components theme for Android
Attribute by attribute
Buttons are arguably the most widely-used components in any app. This is largely due to their versatility, allowing users to perform actions and make choices that ultimately guide the flow of an experience. A single line of contained text and/or an icon indicate the action a button can perform.
Material Buttons are slightly different to traditional Android buttons in that they do not include additional insets (4dp on the left/right) and have more letter-spacing, different default colors and other attributes that improve legibility and affordance amongst other components.
From a design perspective, there are three main types of buttons which are intended to offer hierarchical levels of emphasis:
- Text button (low emphasis): No container. Best used for less important actions, especially when other main content needs to be emphasised.
In addition to this, buttons can be grouped together into a fourth type: Toggle button. This allows related button actions to be horizontally arranged in a common container. The buttons themselves can be selected/deselected to indicate an active/inactive choice.
Basic usage 🏁
A MaterialButton can be included in your layout like so:
Choosing a style 🤔
As discussed in the intro section above, a variety of button types exist. These types map to styles that you can apply to a MaterialButton . There also exists a variety of sub-styles for specific use cases, such as to adjust padding for an icon. The full list of styles and their attributes can be found on GitHub. These style variants inherit from Widget.MaterialComponents.Button , each with an optional style suffix:
- Text button: *.TextButton (main), *.TextButton.Icon , *.TextButton.Snackbar , *.TextButton.Dialog , *.TextButton.Dialog.Icon , *.TextButton.Dialog.Flush
- Outlined button: *.OutlinedButton (main), *.OutlinedButton.Icon
- Contained button (unelevated): *.UnelevatedButton (main), *.UnelevatedButton.Icon
- Contained button (raised): No suffix (default, main), *.Icon
Adding an icon 🔷
An icon can be added to a button. It is displayed at the start, before the text label. In order to get the correct icon padding, it is recommended that you use a *.Icon style variant (shown above in the “Choosing a style” section).
The icon can be added in XML:
Alternatively, it can be done programmatically:
A few additional attributes exist for adjusting the icon size and position:
- iconSize : The width/height of the icon. The default value is the supplied Drawable ’s intrinsic width.
- iconGravity : The gravity of the icon. This can be set to start ( ICON_GRAVITY_START , default, at start of button), end ( ICON_GRAVITY_END , at end of button), textStart ( ICON_GRAVITY_TEXT_START , at start of centered text label) or textEnd ( ICON_GRAVITY_TEXT_END , at end of centered text label).
- iconPadding : The spacing between the icon and the text label. Typically you would not want to change this. The default value is 4dp for text buttons and 8dp for all other types.
Attributes related to icon tinting are discussed in the “Theming” section below.
Grouping Buttons to create a Toggle Button 👨👩👧👦
In order to create a toggle button, we need to add MaterialButton s as child View s to a MaterialButtonToggleGroup (a custom ViewGroup ).
Note: MaterialButtonToggleGroup was added in the 1.1.0-alpha05 release of Material Components for Android.
Grouping
This can be done in XML:
Alternatively, it can be done programmatically:
The MaterialButtonToggleGroup handles layout and adjusting of only the relevant shape corners in the row of MaterialButton s. The appearance of the MaterialButton s is determined by whichever style they each use. It is advised to use a consistent style for all children and also recommended to use the outlined button type.
Adjusting selected behavior
When added to a MaterialButtonToggleGroup , child MaterialButton s automatically become “selectable” (i.e. The android:checkable attribute is set to true).
Thus, there exists a couple of attributes for adjusting how MaterialButtonToggleGroup manages this:
- singleSelection : Determines whether or not only a single button in the group can be checked at a time. The default value is false, meaning multiple buttons can be checked/unchecked independently.
Listening for selection state
We are able to query for and adjust the current checked button(s) in a variety of ways:
We are also able to listen for checked changes by adding an OnButtonCheckedListener to a MaterialButtonToggleGroup :
Listeners can also be removed with the MaterialButtonToggleGroup#removeListener and MaterialButtonToggleGroup#clearListeners functions.
Orientation
The default arrangement of buttons within a toggle group is horizontal. However, seeing as MaterialButtonToggleGroup extends LinearLayout , it also supports vertical arrangement. This can be set programmatically or in XML:
The interesting thing to note here is the extra attributes on the child MaterialButton (s). It is recommended to set the width to match_parent and to remove the top/bottom insets from the child buttons so as to have them sit flush against each other vertically. This also, however, requires adjusting the minHeight to make up for the lack of insets.
Theming 🎨
Buttons can be themed in terms of the three Material Theming subsystems: color, typography and shape. We have already shown which styles to use in the “Choosing a style” section above. When implementing a global custom MaterialButton and MaterialButtonToggleGroup styles, reference them in your app theme with the materialButtonStyle / materialButtonOutlinedStyle and materialButtonToggleGroupStyle attributes respectively.
Color
The color of the MaterialButton background can be customized with the backgroundTint attribute. This requires a ColorStateList , meaning a for checked/enabled/disabled states is required. It defaults to colorPrimary (enabled)/ colorOnSurface (disabled) for contained buttons and transparent(unchecked)/ colorPrimary (checked) for all other types, with different opacities per state. There is also a backgroundTintMode attribute to change the tint PorterDuff.Mode , although typically you would want to keep this the same.
The color of the text label can be customized with the android:textColor attribute. This too requires a ColorStateList . It defaults to colorOnPrimary (enabled)/ colorOnSurface (disabled) for contained buttons and colorPrimary (enabled or checked)/ colorOnSurface (disabled or unchecked) for all other types, with different opacities per state.
The color of the optional icon can be customized with the iconTint attribute. This too requires a ColorStateList and the defaults are the same as those of android:textColor . As before, there is also an iconTintMode attribute.
Lastly, the color of the button touch ripple can be customized with the rippleColor attribute. It too accepts a ColorStateList and defaults to colorOnPrimary for contained buttons and colorPrimary for all other types, with different opacities per state.
Typography
The button text label will adopt the fontFamily attribute defined in your app theme.
While you would typically want to keep most aspects of the button text appearance as is, the Material Guidelines suggest we can use sentence case over the standard all caps for the text label, if desired. To achieve this, we would create a new style:
We could apply this directly to a button or in an individual button style by referencing it with the android:textAppearance attribute. Alternatively, it can be applied globally by referencing it in your app theme with the textAppearanceButton attribute.
Shape
The shape of a button background can be customized with the shapeAppearance attribute. This defaults to shapeAppearanceSmallComponent .
While not strictly shape theming, it is worth mentioning that the width of an outlined button stroke can be adjusted with the strokeWidth attribute. This defaults to 1dp.
More resources 📚
- The source code for the Playground app used in this article can be found on GitHub.
- Buttons Design Documentation
- Buttons API Documentation
- Toggle Buttons API Documentation
I hope this post has provided some insight into Material Buttons and how they can be used in your Android app(s). If you have any questions, thoughts or suggestions then I’d love to hear from you!
Источник
[MaterialButton] Text misalignment with icon with viewStart alignment #1996
Comments
bmc08gt commented Jan 18, 2021 •
Description:
TextAlignment is being offset based on the icon intrinsicWidth when set as viewStart causing the button text to not be properly centered. This is more prominently seen when the button’s width is set at match_constraints as opposed to wrap_content.
Expected behavior:
Button text to remain horizontally centered regardless of icon placement.
Android API version:
API 29 and 30 tested so far
Material Library version:
‘com.google.android.material:material:1.2.1’
Device:
Pixel 3 XL and Pixel 4 XL (so far)
The text was updated successfully, but these errors were encountered:
bmc08gt commented Jan 18, 2021 •
Adjusted the iconPadding based on the intrinsicWidth of the icon is a way to resolve this:
I’ll look into PR’ing this as well.
pekingme commented Jan 20, 2021
Thanks for reporting and opening a PR, @bmc08gt. If I understand correctly, icons should be placed next to text labels to clarify an action and call attention to a button. In case that the button is much wider than the content (icon and text label), the whole content should be centered. Could you elaborate your use case with screenshots a bit more?
bmc08gt commented Jan 20, 2021
the current usecase/requirement is to align the icon to viewStart via iconGravity with the button width being constrained to 80% of width of the screen. With these attributes setup the button’s text isn’t properly centered like it is if you use textStart for the iconGravity . Does that make sense?
pekingme commented Jan 21, 2021
Thanks for clarifying. Here’s the screenshot of two icon buttons respectively using app:iconGravity=»textStart» and app:iconGravity=»start» . The button’s text are aligned.
Not sure if I fully understand what you meant «properly centered». For app:iconGravity=»start» case, the text is not centered with respect to the whole button, but the space left between icon and the other side. Setting the iconPadding to a negative value is the workaround to move the text to the center of the whole button. But I think it’s more like the solution for a special use case. Besides, it can potentially make text and icon overlap on each other when the text is long enough.
Источник
Android materialbutton icon center
Buttons allow users to take actions, and make choices, with a single tap.
Contents
Before you can use Material buttons, you need to add a dependency to the Material Components for Android library. For more information, go to the Getting started page.
Note: is auto-inflated as via MaterialComponentsViewInflater when using a Theme.Material3.* theme.
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.
Toggle button is an additional pattern using a segmented container or icon.
Elevated buttons are essentially outlined buttons with a shadow. To prevent shadow creep, only use them when absolutely necessary, such as when the button requires visual separation from a patterned background.
Elevated button examples
API and source code:
The following example shows an elevated button with a text label.
Adding an icon to an elevated button
The following example shows an elevated button with an icon.
Anatomy and key properties
An elevated button has a text label, a stroked container and an optional icon.
Text label attributes
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Text label | android:text | setText getText | null |
Color | android:textColor | setTextColor getTextColor | ?attr/colorOnSurface (see all states) |
Typography | android:textAppearance | setTextAppearance | ?attr/textAppearanceLabelLarge |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Color | app:backgroundTint | setBackgroundColor setBackgroundTintList getBackgroundTintList | ?attr/colorSurface (see all states) |
Stroke color | app:strokeColor | setStrokeColor setStrokeColorResource getStrokeColor | null |
Stroke width | app:strokeWidth | setStrokeWidth setStrokeWidthResource getStrokeWidth | 0dp |
Shape | app:shapeAppearance | setShapeAppearanceModel getShapeAppearanceModel | ?attr/shapeAppearanceSmallComponent |
Elevation | app:elevation | setElevation getElevation | 1dp |
Ripple color | app:rippleColor | setRippleColor setRippleColorResource getRippleColor | ?attr/colorOnSurface at 16% opacity (see all states) |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Icon | app:icon | setIcon setIconResource getIcon | null |
Color | app:iconTint | setIconTint setIconTintResource getIconTint | ?attr/colorOnSurface (see all states) |
Size | app:iconSize | setIconSize getIconSize | wrap_content |
Gravity (position relative to text label) | app:iconGravity | setIconGravity getIconGravity | start |
Padding (space between icon and text label) | app:iconPadding | setIconPadding getIconPadding | 8dp |
Element | Style |
---|---|
Default style | Widget.Material3.Button.ElevatedButton |
Icon style | Widget.Material3.Button.ElevatedButton.Icon |
See the full list of styles and attrs.
Filled button’s contrasting surface color makes it the most prominent button after the FAB. It’s used for final or unblocking actions in a flow.
Note The filled button is the default style if the style is not set.
Filled button examples
API and source code:
The following example shows a filled button with a text label and a filled container.
Note: Since this is the default type, you don’t need to specify a style tag as long as you are using a Material Components Theme. If not, set the style to @style/Widget.Material3.Button .
Adding an icon to a filled button
The following example shows a filled button with an icon.
Anatomy and key properties
A filled button has a text label, a filled container and an optional icon.
Text label attributes
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Text label | android:text | setText getText | null |
Color | android:textColor | setTextColor getTextColor | ?attr/colorOnPrimary (see all states) |
Typography | android:textAppearance | setTextAppearance | ?attr/textAppearanceLabelLarge |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Color | app:backgroundTint | setBackgroundColor setBackgroundTintList getBackgroundTintList | ?attr/colorPrimary (see all states) |
Stroke color | app:strokeColor | setStrokeColor setStrokeColorResource getStrokeColor | null |
Stroke width | app:strokeWidth | setStrokeWidth setStrokeWidthResource getStrokeWidth | 0dp |
Shape | app:shapeAppearance | setShapeAppearanceModel getShapeAppearanceModel | ?attr/shapeAppearanceSmallComponent |
Elevation | app:elevation | setElevation getElevation | 2dp |
Ripple color | app:rippleColor | setRippleColor setRippleColorResource getRippleColor | ?attr/colorOnPrimary at 16% opacity (see all states) |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Icon | app:icon | setIcon setIconResource getIcon | null |
Color | app:iconTint | setIconTint setIconTintResource getIconTint | ?attr/colorOnPrimary (see all states) |
Size | app:iconSize | setIconSize getIconSize | wrap_content |
Gravity (position relative to text label) | app:iconGravity | setIconGravity getIconGravity | start |
Padding (space between icon and text label) | app:iconPadding | setIconPadding getIconPadding | 8dp |
Element | Style |
---|---|
Default style | Widget.Material3.Button |
Icon style | Widget.Material3.Button.Icon |
Unelevated style | Widget.Material3.Button.UnelevatedButton |
Unelevated icon style | Widget.Material3.Button.UnelevatedButton.Icon |
Default style theme attribute: ?attr/materialButtonStyle
See the full list of styles and attrs.
Filled tonal button
Filled tonal buttons have a lighter background color and darker label color, making them less visually prominent than a regular filled button. They’re still used for final or unblocking actions in a flow, but may be better when these actions don’t require quite so much emphasis.
Filled tonal button examples
API and source code:
The following example shows a filled tonal button with a text label and a filled container.
Adding an icon to a filled tonal button
The following example shows a filled tonal button with an icon.
Anatomy and key properties
A filled tonal button has a text label, a filled container and an optional icon.
Text label attributes
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Text label | android:text | setText getText | null |
Color | android:textColor | setTextColor getTextColor | ?attr/colorOnSecondaryContainer (see all states) |
Typography | android:textAppearance | setTextAppearance | ?attr/textAppearanceLabelLarge |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Color | app:backgroundTint | setBackgroundColor setBackgroundTintList getBackgroundTintList | ?attr/colorSecondaryContainer (see all states) |
Stroke color | app:strokeColor | setStrokeColor setStrokeColorResource getStrokeColor | null |
Stroke width | app:strokeWidth | setStrokeWidth setStrokeWidthResource getStrokeWidth | 0dp |
Shape | app:shapeAppearance | setShapeAppearanceModel getShapeAppearanceModel | ?attr/shapeAppearanceSmallComponent |
Elevation | app:elevation | setElevation getElevation | 2dp |
Ripple color | app:rippleColor | setRippleColor setRippleColorResource getRippleColor | ?attr/colorOnSecondaryContainer at 16% opacity (see all states) |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Icon | app:icon | setIcon setIconResource getIcon | null |
Color | app:iconTint | setIconTint setIconTintResource getIconTint | ?attr/colorOnSecondaryContainer (see all states) |
Size | app:iconSize | setIconSize getIconSize | wrap_content |
Gravity (position relative to text label) | app:iconGravity | setIconGravity getIconGravity | start |
Padding (space between icon and text label) | app:iconPadding | setIconPadding getIconPadding | 8dp |
Element | Style |
---|---|
Default style | Widget.Material3.Button.TonalButton |
Icon style | Widget.Material3.Button.TonalButton.Icon |
See the full list of styles and attrs.
Outlined buttons are for actions that need attention but aren’t the primary action, such as “See all” or “Add to cart.” This is also the button used to give someone the opportunity to change their mind or escape a flow.
Outlined button examples
API and source code:
The following example shows an outlined button with a text label and stroked container.
Adding an icon to an outlined button
The following example shows an outlined button with an icon.
Anatomy and key properties
An outlined button has a text label, a stroked container and an optional icon.
Text label attributes
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Text label | android:text | setText getText | null |
Color | android:textColor | setTextColor getTextColor | ?attr/colorOnSurface (see all states) |
Typography | android:textAppearance | setTextAppearance | ?attr/textAppearanceLabelLarge |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Color | app:backgroundTint | setBackgroundColor setBackgroundTintList getBackgroundTintList | @android:color/transparent (see all states) |
Stroke color | app:strokeColor | setStrokeColor setStrokeColorResource getStrokeColor | ?attr/colorOnSurface at 12% opacity (see all states) |
Stroke width | app:strokeWidth | setStrokeWidth setStrokeWidthResource getStrokeWidth | 1dp |
Shape | app:shapeAppearance | setShapeAppearanceModel getShapeAppearanceModel | ?attr/shapeAppearanceSmallComponent |
Elevation | app:elevation | setElevation getElevation | 0dp |
Ripple color | app:rippleColor | setRippleColor setRippleColorResource getRippleColor | ?attr/colorOnSurface at 16% opacity (see all states) |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Icon | app:icon | setIcon setIconResource getIcon | null |
Color | app:iconTint | setIconTint setIconTintResource getIconTint | ?attr/colorOnSurface (see all states) |
Size | app:iconSize | setIconSize getIconSize | wrap_content |
Gravity (position relative to text label) | app:iconGravity | setIconGravity getIconGravity | start |
Padding (space between icon and text label) | app:iconPadding | setIconPadding getIconPadding | 8dp |
Element | Style |
---|---|
Default style | Widget.Material3.Button.OutlinedButton |
Icon style | Widget.Material3.Button.OutlinedButton.Icon |
Default style theme attribute: ?attr/materialButtonOutlinedStyle
See the full list of styles and attrs.
Text buttons have less visual prominence, so should be used for low emphasis actions, such as when presenting multiple options.
Text button examples
API and source code:
The following example shows a text button with a text label.
Adding an icon to a text button
The following example shows a text button with an icon.
Anatomy and key properties
A text button has a text label, a transparent container and an optional icon.
Text label attributes
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Text label | android:text | setText getText | null |
Color | android:textColor | setTextColor getTextColor | ?attr/colorOnSurface (see all states) |
Typography | android:textAppearance | setTextAppearance | ?attr/textAppearanceLabelLarge |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Color | app:backgroundTint | setBackgroundColor setBackgroundTintList getBackgroundTintList | @android:color/transparent (see all states) |
Stroke color | app:strokeColor | setStrokeColor setStrokeColorResource getStrokeColor | null |
Stroke width | app:strokeWidth | setStrokeWidth setStrokeWidthResource getStrokeWidth | 0dp |
Shape | app:shapeAppearance | setShapeAppearanceModel getShapeAppearanceModel | ?attr/shapeAppearanceSmallComponent |
Elevation | app:elevation | setElevation getElevation | 0dp |
Ripple color | app:rippleColor | setRippleColor setRippleColorResource getRippleColor | ?attr/colorOnSurface at 16% opacity (see all states) |
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Icon | app:icon | setIcon setIconResource getIcon | null |
Color | app:iconTint | setIconTint setIconTintResource getIconTint | ?attr/colorOnSurface (see all states) |
Size | app:iconSize | setIconSize getIconSize | wrap_content |
Gravity (position relative to text label) | app:iconGravity | setIconGravity getIconGravity | start |
Padding (space between icon and text label) | app:iconPadding | setIconPadding getIconPadding | 8dp |
Element | Style |
---|---|
Default style | Widget.Material3.Button.TextButton |
Icon style | Widget.Material3.Button.TextButton.Icon |
Full Width Buttons | Widget.Material3.Button.TextButton.Dialog.FullWidth |
Default style theme attribute: ?attr/borderlessButtonStyle
See the full list of styles and attrs.
Toggle buttons can be used to select from a group of choices.
There are two types of toggle buttons:
To emphasize groups of related toggle buttons, a group should share a common container.
Toggle button examples
API and source code:
The following example shows a toggle button with three buttons that have text labels.
Implementing an icon-only toggle button
The following example shows a toggle button with three buttons that have icons.
Anatomy and key properties
A toggle button has a shared stroked container, icons and/or text labels.
Element | Attribute | Related method(s) | Default value |
---|---|---|---|
Single selection | app:singleSelection | setSingleSelection isSingleSelection | false |
Selection required | app:selectionRequired | setSelectionRequired isSelectionRequired | false |
Element | Style |
---|---|
Default style | Widget.Material3.MaterialButtonToggleGroup |
Default style theme attribute: ?attr/materialButtonToggleGroupStyle
See the full list of styles and attrs.
Icons can be used as toggle buttons when they allow selection, or deselection, of a single choice, such as marking an item as a favorite.
API and source code:
Note The CheckBox API is just one of several inputs that can implement the icon button. See other selection controls for more details.
The following example shows an icon that can be used independently or in items of a RecyclerView .
Buttons support Material Theming and can be customized in terms of color, typography and shape.
Button theming example
API and source code:
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:
Use default style theme attributes, styles and theme overlays. This adds the theme to all buttons but does not affect other components:
Use one of the styles in the layout. That will affect only this button:
Источник