Android  

Custom Slider in Jetpack Compose

Jetpack Compose gives you great flexibility in creating UI components, and the Slider is no exception. While the default slider is quite functional, sometimes design specifications require a more visually tailored experience, such as a thicker track, a custom-colored thumb, or unique active and inactive colors.

In this article, we’ll break down a custom slider implementation in Jetpack Compose that meets these design needs.

Basic Idea

We're building a custom horizontal slider with.

  • A green-colored track and thumb
  • A thicker track (8dp)
  • A white circular thumb (16dp)
  • Consistent coloring for both active and inactive segments
  • Value ranges from 0 to 100
  • Full-width layout with a height of 32dp

Code Overview

Here's the complete code snippet.

Slider(
    value = state.sittingPercentage,
    onValueChange = viewModel::onSittingPercentageChange,
    valueRange = 0f..100f,
    modifier = Modifier
        .fillMaxWidth()
        .height(32.dp),
    colors = SliderDefaults.colors(
        thumbColor = ButtonCommonGreenColor,
        activeTrackColor = ButtonCommonGreenColor,
        inactiveTrackColor = ButtonCommonGreenColor.copy(alpha = 0.3f)
    ),
    track = { sliderPositions ->
        SliderDefaults.Track(
            sliderState = sliderPositions,
            colors = SliderDefaults.colors(
                activeTrackColor = ButtonCommonGreenColor,
                inactiveTrackColor = Color.DarkGray
            ),
            modifier = Modifier.height(8.dp),
            thumbTrackGapSize = 0.dp,
            drawStopIndicator = { null }
        )
    },
    thumb = {
        Box(
            modifier = Modifier
                .size(16.dp)
                .background(White, shape = CircleShape)
        )
    }
)

Explanation of Each Part

value and onValueChange

These handle the current value of the slider and update the view model when the user interacts with it.

value = state.sittingPercentage,
onValueChange = viewModel::onSittingPercentageChange,

valueRange = 0f..100f

Limits the slider between 0 and 100. Perfect for percentage-based values.

Colors (Top-Level)

colors = SliderDefaults.colors(
    thumbColor = ButtonCommonGreenColor,
    activeTrackColor = ButtonCommonGreenColor,
    inactiveTrackColor = ButtonCommonGreenColor.copy(alpha = 0.3f)
)
  • thumbColor: Sets the color of the draggable thumb.
  • activeTrackColor: Color of the line from the start to the thumb.
  • inactiveTrackColor: Color from the thumb to the end.

This creates a consistent green look across all parts, with the inactive segment being a faded version.

Track

track = { sliderPositions ->
    SliderDefaults.Track(
        sliderState = sliderPositions,
        colors = SliderDefaults.colors(
            activeTrackColor = ButtonCommonGreenColor,
            inactiveTrackColor = Color.DarkGray
        ),
        modifier = Modifier.height(8.dp),
        thumbTrackGapSize = 0.dp,
        drawStopIndicator = { null }
    )
}
  • This is a custom track that replaces the default.
  • Uses a height of 8dp for a thicker visual appearance.
  • thumbTrackGapSize = 0.dp: Ensures the track touches the thumb precisely.
  • drawStopIndicator = { null }: Prevents drawing any stop indicators (used for stepped sliders).

Thumb

thumb = {
    Box(
        modifier = Modifier
            .size(16.dp)
            .background(White, shape = CircleShape)
    )
}
  • This replaces the default thumb with a custom white circle.
  • The size is 16dp, and it utilizes a CircleShape for a perfect round appearance.

This makes the thumb visually distinct from the track, giving a polished, tactile appearance.

Output

Output

When Should You Use This?

This custom slider approach is practical when.

  • You're following a strict design system.
  • You want to enhance visual clarity (e.g., by increasing track thickness).
  • You want your slider to stand out (e.g., as a key interaction point, such as volume or rating).

Final Thoughts

Jetpack Compose makes customizing sliders seamless. With a few tweaks, you can build a slider that feels both elegant and functional, like the one above, clean, consistent, and user-friendly.