Back to Material Components Android

Slider

docs/components/Slider.md

1.13.019.9 KB
Original Source
<!--docs: title: "Sliders" layout: detail section: components excerpt: "Sliders allow users to make selections from a range of values." iconId: slider path: /catalog/sliders/ -->

Slider

Sliders let users make selections from a range of values. There are three variants of sliders.

  1. Standard
  2. Centered
  3. Range

Note: Images use various dynamic color schemes.

Design & API documentation

Anatomy

  1. Value indicator (optional)
  2. Stop indicators (optional)
  3. Active track
  4. Handle
  5. Inactive track
  6. Inset icon (optional)

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.

The slider includes expressive configurations for orientation, shape sizes, and an inset icon. More on M3 Expressive

Types and naming:

  • Changed continuous slider to standard slider
  • The discrete slider is now the stops configuration

New configurations:

  • Orientation: Horizontal, vertical
  • Optional inset icon (standard slider only)
  • Sizes: XS (existing default), S, M, L, XL

M3 Expressive styles

The expressive slider comes with 5 pre-defined styles varying in track thickness and corner size:

  • Widget.Material3Expressive.Slider.Xsmall (default)
  • Widget.Material3Expressive.Slider.Small
  • Widget.Material3Expressive.Slider.Medium
  • Widget.Material3Expressive.Slider.Large
  • Widget.Material3Expressive.Slider.Xlarge

Key properties

Track attributes

ElementAttributeRelated method(s)Default value
Orientationandroid:orientationsetOrientation
isVerticalhorizontal
Min valueandroid:valueFromsetValueFrom
getValueFromN/A
Max valueandroid:valueTosetValueTo
getValueToN/A
Step size (discrete)android:stepSizesetStepSize
getStepSizeN/A
Initial selected value (Slider)android:valuesetValue
getValueN/A
Initial selected values (RangeSlider)app:valuessetValues
getValuesN/A
Centeredapp:centeredsetCentered
isCenteredfalse
Continuous mode tick countapp:continuousModeTickCountsetContinuousModeTickCount
getContinuousModeTickCount0
Heightapp:trackHeightsetTrackHeight
getTrackHeight16dp
Colorapp:trackColorsetTrackTintList
getTrackTintListnull
Color for track's active partapp:trackColorActivesetTrackActiveTintList
getTrackActiveTintList?attr/colorPrimary
Color for track's inactive partapp:trackColorInactivesetTrackInactiveTintList
getTrackInactiveTintList?attr/colorSurfaceContainerHighest
Corner sizeapp:trackCornerSizesetTrackCornerSize
getTrackCornerSizetrackHeight / 2
Inside corner sizeapp:trackInsideCornerSizesetTrackInsideCornerSize
getTrackInsideCornerSize2dp
Stop indicator sizeapp:trackStopIndicatorSizesetTrackStopIndicatorSize
getTrackStopIndicatorSize4dp
Minimum separation for adjacent thumbsapp:minSeparationsetMinSeparation
getMinSeparation0dp
Active start iconapp:trackIconActiveStartsetTrackIconActiveStart
getTrackIconActiveStartnull
Active end iconapp:trackIconActiveEndsetTrackIconActiveEnd
getTrackIconActiveEndnull
Active icon colorapp:trackIconActiveColorsetTrackIconActiveColor
getTrackIconActiveColorN/A
Inactive start iconapp:trackIconInactiveStartsetTrackIconInactiveStart
getTrackIconInactiveStartnull
Inactive end iconapp:trackIconInactiveEndsetTrackIconInactiveEnd
getTrackIconInactiveEndnull
Inactive icon colorapp:trackIconInactiveColorsetTrackIconInactiveColor
getTrackIconInactiveColorN/A
Icon sizeapp:trackIconSizesetTrackIconSize
getTrackIconSizeN/A

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.

Note: vertical orientation still uses height in the same way as for horizontal orientation. In this context, height can be seen as track thickness.

Thumb attributes

ElementAttributeRelated method(s)Default value
Colorapp:thumbColorsetThumbTintList
getThumbTintList?attr/colorPrimary
Widthapp:thumbWidthsetThumbWidth
setThumbWidthResource
getThumbWidth4dp
Heightapp:thumbHeightsetThumbHeight
setThumbHeightResource
getThumbHeight44dp
Radiusapp:thumbRadiussetThumbRadiusResource
setThumbRadius
getThumbRadiusN/A
Elevationapp:thumbElevationsetThumbElevationResource
setThumbElevation
getThumbElevation2dp
Halo colorapp:haloColorsetHaloTintList
getHaloTintList@android:color/transparent
Halo radiusapp:haloRadiussetHaloRadiusResource
setHaloRadius
getHaloRadiusN/A
Stroke colorapp:thumbStrokeColorsetThumbStrokeColor
setThumbStrokeColorResource
getThumbStrokeColornull
Stroke widthapp:thumbStrokeWidthsetThumbStrokeWidth
setThumbStrokeWidthResource
getThumbStrokeWidth0dp
Gap sizeapp:thumbTrackGapSizesetThumbTrackGapSize
getThumbTrackGapSize6dp

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
hasLabelFormatternull
Behaviorapp:labelBehaviorsetLabelBehavior
getLabelBehaviorfloating

Note: The value label is a Tooltip.

Tick mark attributes

ElementAttributeRelated method(s)Default value
Colorapp:tickColorsetTickTintList
getTickTintListnull
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
getTickActiveRadiusnull (1/2 trackStopIndicatorSize)
Radius for tick's inactive partapp:tickRadiusInactivesetTickInactiveRadius
getTickInactiveRadiusnull (1/2 trackStopIndicatorSize)
Tick visible (deprecated)app:tickVisiblesetTickVisible
isTickVisible()true
Tick visibility modeapp:tickVisibilityModesetTickVisibilityMode
getTickVisibilityMode()autoLimit

Note: app:tickColor takes precedence over app:tickColorActive and app:tickColorInactive. It's a shorthand for setting both values to the same thing.

Note: app:tickVisible is deprecated in favor of app:tickVisibilityMode.

Styles

ElementStyleTheme attribute
Default styleWidget.Material3.Slider?attr/sliderStyle

For the full list, see 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

Variants of sliders

Standard slider

Standard sliders select one value from a range of values. Use this when the slider should start from zero or the beginning of a sequence.

API and source code:

Add a Standard slider to a 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" />

Add a standard slider with stop indicator to a layout:

Stop indicators show which predetermined values can be chosen on the slider. The slider handle snaps to the closest stop.

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

Centered slider

Centered sliders select a value from a positive and negative value range. Use this when zero, or the default value, is in the middle of the range.

Add a centered slider to a 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="0.0"
    android:valueFrom="-100.0"
    android:valueTo="100.0" />

Range slider

A slider with two thumbs is called a range slider. Range sliders select two values on one slider to create a range. Use this when defining a minimum and maximum value.

Add a range slider to a 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" />

Add a range slider with stop indicator to a layout:

Stop indicators show which predetermined values can be chosen on the slider. The slider handle snaps to the closest stop.

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

Code implementation

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.

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.

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())
}

Customizing sliders

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