Skip to content

Slider ​

Sliders allow users to make selections from a range of values.

"Slider animation."

Contents

Design and API Documentation ​

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 ​

Add a Slider to a layout:

xml
<!-- 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"  />

Observe changes to a slider:

kt
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
}

API and source code:

Range slider

A slider with two thumbs is called a range slider. Add a RangeSlider to a layout:

xml
<!-- Continuous slider -->
<com.google.android.material.slider.RangeSlider
    ...
    android:valueFrom="0.0"
    android:valueTo="100.0"
    app:values="@array/initial_slider_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:

xml
<resources>
  <array name="initial_slider_values">
    <item>20.0</item>
    <item>70.0</item>
  </array>
</resources>

Observe changes to a range slider:

kt
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
}

API and source code:

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:

kt
slider.contentDescription = contentDescription

If using a TextView to display the value of the slider, you should set android:labelFor so that screen readers announce that TextView refers to the slider.

The minimum touch target size of the thumb is 48dp by default. If a different size is needed, please set minTouchTargetSize in the style or the layout.

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 view
  • withinBounds - draws the label floating within the bounds of this view
  • gone - prevents the label from being drawn
  • visible - always draws the label

Note: there's a known issue where the label doesn't scroll along with the screen when the slider is in a scrollable container and app:labelBehavior=visible. To work around that you should either use a different mode or hide the label on scroll.

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 price range in USD currency.

In code:

kt
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

Continuous slider ​

Continuous sliders allow users to make meaningful selections that don’t require a specific value.

The following example shows a continuous slider.

In the layout:

xml
<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 ​

The following example shows a continuous range slider.

In the layout:

xml
<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.

The following example shows a discrete slider.

In the layout:

xml
<com.google.android.material.slider.Slider
    ...
    android:stepSize="10.0" />

Discrete range slider ​

The following example shows a discrete range slider.

In the layout:

xml
<com.google.android.material.slider.RangeSlider
    ...
    android:stepSize="10.0"  />

Anatomy and key properties ​

A slider has a track, one or two thumbs, and an optional value label. A discrete slider also has tick marks.

  1. Value label (optional)
  2. Active track stop indicator
  3. Active track
  4. Thumb
  5. Inactive track
  6. Inactive track stop indicator

Track attributes ​

ElementAttributeRelated method(s)Default value
Min valueandroid:valueFromsetValueFrom
getValueFrom
N/A
Max valueandroid:valueTosetValueTo
getValueTo
N/A
Step size (discrete)android:stepSizesetStepSize
getStepSize
N/A
Initial selected value (Slider)android:valuesetValue
getValue
N/A
Initial selected values (RangeSlider)app:valuessetValues
getValues
N/A
Heightapp:trackHeightsetTrackHeight
getTrackHeight
16dp
Colorapp:trackColorsetTrackTintList
getTrackTintList
null
Color for track's active partapp:trackColorActivesetTrackActiveTintList
getTrackActiveTintList
?attr/colorPrimary
Color for track's inactive partapp:trackColorInactivesetTrackInactiveTintList
getTrackInactiveTintList
?attr/colorSurfaceContainerHighest
Inside corner sizeapp:trackInsideCornerSizesetTrackInsideCornerSize
getTrackInsideCornerSize
2dp
Stop indicator sizeapp:trackStopIndicatorSizesetTrackStopIndicatorSize
getTrackStopIndicatorSize
4dp
Minimum separation for adjacent thumbsapp:minSeparationsetMinSeparation
getMinSeparation
0dp

Note: app:trackColor takes precedence over app:trackColorActive and app:trackColorInative. It's a shorthand for setting both values to the same thing.

Note: app:trackStopIndicatorSize takes precedence over app:tickRadiusActive and app:tickRadiusInactive.

Thumb attributes ​

ElementAttributeRelated method(s)Default value
Colorapp:thumbColorsetThumbTintList
getThumbTintList
?attr/colorPrimary
Widthapp:thumbWidthsetThumbWidth
setThumbWidthResource
getThumbWidth
4dp
Heightapp:thumbHeightsetThumbHeight
setThumbHeightResource
getThumbHeight
44dp
Radiusapp:thumbRadiussetThumbRadiusResource
setThumbRadius
getThumbRadius
N/A
Elevationapp:thumbElevationsetThumbElevationResource
setThumbElevation
getThumbElevation
2dp
Halo colorapp:haloColorsetHaloTintList
getHaloTintList
@android:color/transparent
Halo radiusapp:haloRadiussetHaloRadiusResource
setHaloRadius
getHaloRadius
N/A
Stroke colorapp:thumbStrokeColorsetThumbStrokeColor
setThumbStrokeColorResource
getThumbStrokeColor
null
Stroke widthapp:thumbStrokeWidthsetThumbStrokeWidth
setThumbStrokeWidthResource
getThumbStrokeWidth
0dp
Gap sizeapp:thumbTrackGapSizesetThumbTrackGapSize
getThumbTrackGapSize
6dp

Note: app:thumbWidth and app:thumbHeight take precedence over app:thumbRadius.

Value label attributes ​

ElementAttributeRelated method(s)Default value
Styleapp:labelStyleN/A@style/Widget.Material3.Tooltip
FormatterN/AsetLabelFormatter
hasLabelFormatter
null
Behaviorapp:labelBehaviorsetLabelBehavior
getLabelBehavior
floating

Note: The value label is a Tooltip.

Tick mark attributes ​

ElementAttributeRelated method(s)Default value
Colorapp:tickColorsetTickTintList
getTickTintList
null
Color for tick's active partapp:tickColorActivesetTickActiveTintList
getTickActiveTintList
?attr/colorSurfaceContainerHighest
Color for tick's inactive partapp:tickColorInactivesetTickInactiveTintList
getTickInactiveTintList
?attr/colorPrimary
Radius for tick's active partapp:tickRadiusActivesetTickActiveRadius
getTickActiveRadius
null (1/2 trackStopIndicatorSize)
Radius for tick's inactive partapp:tickRadiusInactivesetTickInactiveRadius
getTickInactiveRadius
null (1/2 trackStopIndicatorSize)
Tick visibleapp:tickVisiblesetTickVisible
isTickVisible()
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 ​

ElementStyle
Default styleWidget.Material3.Slider

Default style theme attribute: ?attr/sliderStyle

See the full list of styles and attributes.

Non-Text Contrast update ​

In order to comply with the latest accessibility requirements, the Slider has been updated with additional attributes:

  • app:thumbTrackGapSize: size of the gap between the thumb and the track, 6dp by default.
  • app:trackInsideCornerSize: size of the corners towards the thumb when a gap is present, 2dp by default.
  • app:trackStopIndicatorSize: size of the stop at the start/end of the track, 4dp by default.

*.Legacy styles have been added to revert to the previous behavior (not recommended):

  • Widget.Material3.Slider.Legacy

Theming sliders ​

Sliders support Material Theming which can customize color and typography.

Slider theming example ​

API and source code:

The following example shows a range slider with Material Theming.

Implementing slider theming ​

Use theme attributes and styles in res/values/styles.xml which applies to all sliders and affects other components:

xml
<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="colorOnSurface">@color/shrine_pink_100</item>
</style>

Use a default style theme attribute, styles and a theme overlay which applies to all sliders but does not affect other components:

xml
<style name="Theme.App" parent="Theme.Material3.*">
    ...
    <item name="sliderStyle">@style/Widget.App.Slider</item>
</style>

<style name="Widget.App.Slider" parent="Widget.Material3.Slider.Legacy">
    <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.Material3.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.Material3.BodySmall">
  <item name="android:textColor">@color/shrine_pink_100</item>
  <item name="fontFamily">@font/rubik</item>
  <item name="android:fontFamily">@font/rubik</item>
</style>

Use the style in the layout, which affects only this specific slider:

xml
<com.google.android.material.slider.RangeSlider
    ...
    style="@style/Widget.App.Slider"  />
Slider has loaded