Resolves https://github.com/material-components/material-components-android/pull/1653 Resolves https://github.com/material-components/material-components-android/issues/1652 GIT_ORIGIN_REV_ID=ba5cab25a210a34e9d6396101ad045c8cfc8cb92 PiperOrigin-RevId: 328542122
16 KiB
Slider
Sliders allow users to make selections from a range of values.
Contents
Using sliders
Before you can use Material sliders, you need to add a dependency to the Material Components for Android library. For more information, go to the Getting started page.
Usage
A Slider can be added in a layout like so:
<!-- Continuous slider -->
<com.google.android.material.slider.Slider
...
android:valueFrom="0.0"
android:valueTo="100.0" />
<!-- Discrete slider -->
<com.google.android.material.slider.Slider
...
android:valueFrom="0.0"
android:valueTo="100.0"
android:stepSize="10.0" />
Changes to a slider can be observed like so:
slider.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: Slider) {
// Responds to when slider's touch event is being started
}
override fun onStopTrackingTouch(slider: Slider) {
// Responds to when slider's touch event is being stopped
}
})
slider.addOnChangeListener { slider, value, fromUser ->
// Responds to when slider's value is changed
}
Similarly, a RangeSlider can be added in a layout like so:
<!-- Continuous slider -->
<com.google.android.material.slider.RangeSlider
...
android:valueFrom="0.0"
android:valueTo="100.0"
app:values="@array/initial_values" />
<!-- Discrete slider -->
<com.google.android.material.slider.RangeSlider
...
android:valueFrom="0.0"
android:valueTo="100.0"
app:values="@array/initial_slider_values"
android:stepSize="10.0" />
And in values/arrays.xml:
<resources>
<array name="initial_slider_values">
<item>20.0</item>
<item>70.0</item>
</array>
</resources>
Changes to a range slider can be observed like so:
rangeSlider.addOnSliderTouchListener(object : RangeSlider.OnSliderTouchListener {
override fun onStartTrackingTouch(slider: RangeSlider) {
// Responds to when slider's touch event is being started
}
override fun onStopTrackingTouch(slider: RangeSlider) {
// Responds to when slider's touch event is being stopped
}
})
rangeSlider.addOnChangeListener { rangeSlider, value, fromUser ->
// Responds to when slider's value is changed
}
Making sliders accessible
Sliders support setting content descriptors for use with screen readers. While optional, we strongly encourage their use.
That can be done in XML via the android:contentDescription attribute or
programmatically like so:
slider.contentDescription = contentDescription
Additionaly, if using a TextView to display the value of the slider, you
should set android:labelFor on it, so that screen readers announce that
TextView refers to the slider.
Adding/removing the value label
By default, the slider will show a value label above the thumb when it's
selected. You can change how it's drawn via the app:labelBehavior attribute or
setLabelBehavior method.
The modes of app:labelBehavior are:
floating(default) - draws the label floating above the bounds of this viewwithinBounds- draws the label floating within the bounds of this viewgone- prevents the label from being drawn
Setting a LabelFormatter
By using a LabelFormatter you can display the selected value using letters to
indicate magnitude (e.g.: 1.5K, 3M, 12B). That can be achieved through the
setLabelFormatter method.
The following example shows a slider for a prince range in the USD currency.
In code:
rangeSlider.setLabelFormatter { value: Float ->
val format = NumberFormat.getCurrencyInstance()
format.maximumFractionDigits = 0
format.currency = Currency.getInstance("USD")
format.format(value.toDouble())
}
Types
There are two types of sliders: 1. Continuous slider, 2. Discrete slider
A slider with two thumbs is called a range slider.
Continuous slider
Continuous sliders allow users to make meaningful selections that don’t require a specific value.
API and source code:
Slider
The following example shows a continuous slider.
In the layout:
<com.google.android.material.slider.Slider
android:id="@+id/slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/slider_desc"
android:value="20.0"
android:valueFrom="0.0"
android:valueTo="100.0" />
Continuous range slider
API and source code:
RangeSlider
The following example shows a continuous range slider.
In the layout:
<com.google.android.material.slider.RangeSlider
android:id="@+id/range_slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:contentDescription="@string/slider_desc"
app:values="@array/initial_slider_values"
android:valueFrom="0.0"
android:valueTo="100.0" />
Discrete slider
Discrete sliders display a numeric value label upon pressing the thumb, which allows a user to input an exact value.
API and source code:
Slider
The following example shows a discrete slider.
In the layout:
<com.google.android.material.slider.Slider
...
android:stepSize="5.0" />
Discrete range slider
API and source code:
RangeSlider
The following example shows a discrete range slider.
In the layout:
<com.google.android.material.slider.RangeSlider
...
android:stepSize="5.0" />
Anatomy and key properties
A slider has a track, one or two thumbs, and optional value label. A discrete slider also has tick marks.
- Track
- Thumb
- Value label (optional)
- Tick mark (discrete sliders)
Track attributes
| Attribute | Related method(s) | Default value | |
|---|---|---|---|
| Min value | android:valueFrom |
setValueFromgetValueFrom |
N/A |
| Max value | android:valueTo |
setValueTogetValueTo |
N/A |
| Step size (discrete) | android:stepSize |
setStepSizegetStepSize |
N/A |
| Initial selected value (Slider) | android:value |
setValuegetValue |
N/A |
| Initial selected values (RangeSlider) | app:values |
setValuesgetValues |
N/A |
| Height | app:trackHeight |
setTrackHeightgetTrackHeight |
4dp |
| Color | app:trackColor |
setTrackTintListgetTrackTintList |
null |
| Color for track's active part | app:trackColorActive |
setTrackActiveTintListgetTrackActiveTintList |
?attr/colorPrimary |
| Color for track's inactive part | app:trackColorInactive |
setTrackInactiveTintListgetTrackInactiveTintList |
?attr/colorPrimary at 24% |
| Minimum separation for adjacent thumbs | app:minSeparation |
setMinSeparationgetMinSeparation |
0dp |
Note: app:trackColor takes precedence over app:trackColorActive and
app:trackColorInative. It's a shorthand for setting both values to the same
thing.
Thumb attributes
| Attribute | Related method(s) | Default value | |
|---|---|---|---|
| Color | app:thumbColor |
setThumbTintListgetThumbTintList |
?attr/colorPrimary |
| Radius | app:thumbRadius |
setThumbRadiusResourcesetThumbRadiusgetThumbRadius |
10dp |
| Elevation | app:thumbElevation |
setThumbElevationResourcesetThumbElevationgetThumbElevation |
1dp |
| Halo color | app:haloColor |
setHaloTintListgetHaloTintList |
?attr/colorPrimary at 24% |
| Halo radius | app:haloRadius |
setHaloRadiusResourcesetHaloRadiusgetHaloRadius |
24dp |
| Stroke color | app:thumbStrokeColor |
setThumbStrokeColorsetThumbStrokeColorResourcegetThumbStrokeColor |
null |
| Stroke width | app:thumbStrokeWidth |
setThumbStrokeWidthsetThumbStrokeWidthResourcegetThumbStrokeWidth |
0dp |
Value label attributes
| Attribute | Related method(s) | Default value | |
|---|---|---|---|
| Style | app:labelStyle |
N/A | @style/Widget.MaterialComponents.Tooltip |
| Formatter | N/A | setLabelFormatterhasLabelFormatter |
null |
| Behavior | app:labelBehavior |
setLabelBehaviorgetLabelBehavior |
floating |
Note: The value label is a Tooltip.
Tick mark attributes
| Attribute | Related method(s) | Default value | |
|---|---|---|---|
| Color | app:tickColor |
setTickTintListgetTickTintList |
null |
| Color for track's active part | app:tickColorActive |
setTickActiveTintListgetTickActiveTintList |
?attr/colorOnPrimary at 54% |
| Color for track's inactive part | app:tickColorInactive |
setTickInactiveTintListgetTickInactiveTintList |
?attr/colorPrimary at 54% |
| Tick visible | app:tickVisible |
setTickVisibleisTickVisible() |
true |
Note: app:tickColor takes precedence over app:tickColorActive and
app:tickColorInative. It's a shorthand for setting both values to the same
thing.
Styles
| Style | |
|---|---|
| Default style | Widget.MaterialComponents.Slider |
Default style theme attribute: ?attr/sliderStyle
See the full list of styles and attributes.
Theming sliders
Sliders support Material Theming and can be customized in terms of color and typography.
Slider theming example
API and source code:
SliderRangeSlider
The following example shows a range slider with Material Theming.
Implementing slider theming
Using theme attributes and styles in res/values/styles.xml (themes all sliders
and affects other components):
<style name="Theme.App" parent="Theme.MaterialComponents.*">
...
<item name="colorPrimary">@color/shrine_pink_100</item>
<item name="colorOnPrimary">@color/shrine_pink_900</item>
<item name="colorOnSurface">@color/shrine_pink_100</item>
</style>
or using a default style theme attribute, styles and a theme overlay (themes all sliders but does not affect other components):
<style name="Theme.App" parent="Theme.MaterialComponents.*">
...
<item name="sliderStyle">@style/Widget.App.Slider</item>
</style>
<style name="Widget.App.Slider" parent="Widget.MaterialComponents.Slider">
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Slider</item>
<item name="labelStyle">@style/Widget.App.Tooltip</item>
</style>
<style name="ThemeOverlay.App.Slider" parent="">
<item name="colorPrimary">@color/shrine_pink_100</item>
<item name="colorOnPrimary">@color/shrine_pink_900</item>
<item name="colorOnSurface">@color/shrine_pink_100</item>
</style>
<style name="Widget.App.Tooltip" parent="Widget.MaterialComponents.Tooltip">
<item name="android:textAppearance">@style/TextAppearance.App.Tooltip</item>
<item name="backgroundTint">@color/shrine_pink_900</item>
</style>
<style name="TextAppearance.App.Tooltip" parent="TextAppearance.MaterialComponents.Tooltip">
<item name="android:textColor">@color/shrine_pink_100</item>
<item name="fontFamily">@font/rubik</item>
<item name="android:fontFamily">@font/rubik</item>
</style>
or using the style in the layout (affects only this specific slider):
<com.google.android.material.slider.RangeSlider
...
style="@style/Widget.App.Slider" />










