Jetpack Compose Slider (with Examples)

Jetpack Compose Slider

In this article, we will learn how to implement Slider and RangeSlider APIs in Jetpack Compose with examples.

Prerequisites:

What is a Slider in Jetpack Compose?

Sliders allow users to make selections from a range of values. They are ideal for adjusting settings such as volume and brightness, or for applying image filters.

Example:

simple slider example in Jetpack Compose

Slider Anatomy:

The slider contains a track, thumb, value label, and tick marks.

1. Track
2. Thumb
3. Value label (optional)
4. Tick mark (optional)

For this article, open MainActivity, create a MyUI() composable and call it from the onCreate() method.

import android.content.Context
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourProjectNameTheme(darkTheme = false) {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    Column(
                        modifier = Modifier
                            .fillMaxSize()
                            .padding(all = 4.dp),
                        verticalArrangement = Arrangement.Center,
                        horizontalAlignment = Alignment.CenterHorizontally
                    ) {
                        MyUI()
                    }
                }
            }
        }
    }
}

@Composable
private fun MyUI() {

}

We will write our code in MyUI().

Jetpack Compose provides Slider API. It looks like this:

@Composable
fun Slider(
    value: Float,
    onValueChange: (Float) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
    /*@IntRange(from = 0)*/
    steps: Int = 0,
    onValueChangeFinished: (() -> Unit)? = null,
    interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
    colors: SliderColors = SliderDefaults.colors()
)

value – It is the current value of the slider.

onValueChange – It is a lambda that gets called every time the value is changed.

modifier – It is to modify the layout (for example, changing the width).

enabled – A boolean value that indicates if the user can interact with the slider.

valueRange – The range of values that the slider can take.

steps – It indicates if the slider specifies continuous or discrete values. Any value higher than 0 denotes discrete, while 0 denotes continuous. It should not be negative.

onValueChangeFinished – It is called when the value change has been finished (i.e., when the user has completed selecting a new value by ending a drag or a click).

interactionSource – It helps us to observe and customize the interactions. For example, you can disable the ripple effect.

colors – We can customize the thumb, track, and tick mark colors.

Simple Slider Example:

For the proper functioning of the slider, value and onValueChange parameters are mandatory.

@Composable
private fun MyUI() {

    var sliderValue by remember {
        mutableStateOf(0f) // pass the initial value
    }

    Slider(
        value = sliderValue,
        onValueChange = { sliderValue_ ->
            sliderValue = sliderValue_
        },
        onValueChangeFinished = {
            // this is called when the user completed selecting the value
            Log.d("MainActivity", "sliderValue = $sliderValue")
        },
        valueRange = 0f..10f
    )

    Text(text = sliderValue.toString())
}

Output:

simple slider example in Jetpack Compose

Related: State Management in Jetpack Compose

Vertical Slider:

There is no separate composable for the vertical slider. We can rotate the Slider() by 90 degrees to make it become vertical.

@Composable
private fun MyUI() {

    var sliderValue by remember {
        mutableStateOf(0f)
    }

    Slider(
        modifier = Modifier
            .width(width = 130.dp)
            .rotate(degrees = -90f),
        value = sliderValue,
        onValueChange = { sliderValue_ ->
            sliderValue = sliderValue_
        },
        onValueChangeFinished = {
            // this is called when the user completed selecting the value
            Log.d("MainActivity", "sliderValue = $sliderValue")
        },
        valueRange = 0f..5f
    )
}

Output:

vertical slider

Slider Thumb and Track Colors:

We can customize the slider colors with the help of SliderDefaults.colors() method. It looks like this:

@Composable
public final fun colors(
    thumbColor: Color,
    disabledThumbColor: Color,
    activeTrackColor: Color,
    inactiveTrackColor: Color,
    disabledActiveTrackColor: Color,
    disabledInactiveTrackColor: Color,
    activeTickColor: Color,
    inactiveTickColor: Color,
    disabledActiveTickColor: Color,
    disabledInactiveTickColor: Color
): SliderColors

Example:

@Composable
private fun MyUI() {

    var sliderValue by remember {
        mutableStateOf(0f)
    }

    Slider(
        value = sliderValue,
        onValueChange = { sliderValue_ ->
            sliderValue = sliderValue_
        },
        onValueChangeFinished = {
            // this is called when the user completed selecting the value
            Log.d("MainActivity", "sliderValue = $sliderValue")
        },
        valueRange = 0f..10f,
        colors = SliderDefaults.colors(
            thumbColor = Color.Green,
            activeTrackColor = Color.Magenta
        )
    )

    Text(text = sliderValue.toString())
}

Output:

Slider Thumb and Track Colors

Discrete Slider:

Discrete sliders display a numeric value label.

Example:

jetpack compose discrete slider example

We can create discrete sliders by passing an integer value to the steps parameter. The integer should be greater than 0. It represents the number of tick marks between the start and end values.

Example 1: valueRange = 0, 2, 4…..10.

Here, 0 and 10 are the start and end values. The steps value is the same as the number of tick marks between them. You can use the following formula to calculate it:

slider steps value

steps value = (10 – 0) / 2 – 1 = 4

Example 2: valueRange = 1, 3, 5….15

Start value = 1
End value = 15
Difference between two successive numbers = 2

steps value = (15 – 1) / 2 – 1 = 6

Note: The numbers in the valueRange should be evenly distributed. If not, you get some floating values when you tap on the tick marks.

Example code:

@Composable
private fun MyUI() {

    var sliderValue by remember {
        mutableStateOf(0f)
    }

    Slider(
        value = sliderValue,
        onValueChange = { sliderValue_ ->
            sliderValue = sliderValue_
        },
        onValueChangeFinished = {
            // this is called when the user completed selecting the value
            Log.d("MainActivity", "sliderValue = $sliderValue")
        },
        valueRange = 0f..10f,
        steps = 4
    )

    Text(text = sliderValue.toString())
}

Output:

jetpack compose discrete slider example

Range Slider in Jetpack Compose:

RangeSlider is similar to the Slider but allows the user to select two values. The two values are within the value range but cannot cross each other.

Example:

Range Slider Example

RangeSlider() API is currently experimental:

@Composable
@ExperimentalMaterialApi
fun RangeSlider(
    value: ClosedFloatingPointRange<Float>,
    onValueChange: (ClosedFloatingPointRange<Float>) -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    valueRange: ClosedFloatingPointRange<Float> = 0f..1f,
    /*@IntRange(from = 0)*/
    steps: Int = 0,
    onValueChangeFinished: (() -> Unit)? = null,
    colors: SliderColors = SliderDefaults.colors()
) 

Example:

@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun MyUI() {

    var sliderValues by remember {
        mutableStateOf(1f..20f) // pass the initial values
    }

    RangeSlider(
        value = sliderValues,
        onValueChange = { sliderValues_ ->
            sliderValues = sliderValues_
        },
        valueRange = 1f..20f,
        onValueChangeFinished = {
            // this is called when the user completed selecting the value
            Log.d(
                "MainActivity",
                "First: ${sliderValues.start}, Last: ${sliderValues.endInclusive}"
            )
        }
    )

    Text(text = "Start: ${sliderValues.start}, End: ${sliderValues.endInclusive}")
}

Output:

Range Slider Example

Similar to the discrete slider, we can create a discrete range slider using the steps parameter.

Discrete Range Slider:

@OptIn(ExperimentalMaterialApi::class)
@Composable
private fun MyUI() {

    var sliderValues by remember {
        mutableStateOf(0f..10f)
    }

    RangeSlider(
        value = sliderValues,
        onValueChange = { sliderValues_ ->
            sliderValues = sliderValues_
        },
        valueRange = 0f..10f,
        onValueChangeFinished = {
            // this is called when the user completed selecting the value
            Log.d(
                "MainActivity",
                "First: ${sliderValues.start}, Last: ${sliderValues.endInclusive}"
            )
        },
        steps = 4
    )

    Text(text = "Start: ${sliderValues.start}, End: ${sliderValues.endInclusive}")
}

Output:

Discrete Range Slider

This is all about Slider and RangeSlider APIs in Android Jetpack Compose. I hope you have learned something new. If you have any doubts, leave a comment below.

Related Articles:

References:

Leave a Comment