Create A Custom Vertical Slider In Compose for Android
Create a custom vertical slider in Android Compose for your next project.

In this post I will show you how I created a vertical slider in Compose for Android.

Android Vertical Slider

Process

The root element is the slider composable. We will rotate it using the graphicsLayer Modifier.

This sample is taken from one of my projects and could be polished to fit your needs. I changed a bit of the parent elements and the location of it to fit in the center of the screen in either orientation, vertical or horizontal. Upon implementation, you may need to adjust the offsets depending on how and where you place it.

While the slider position is changed, there is a circle and Text to follow the location of the thumb element.

I created variables to hold the size of the vertical slider in Compose for my use case. You may not need this either. You could create a fixed size.

Code

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContent {
            SampleVerticalSliderTheme {
                Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
                    Box(
                        modifier = Modifier
                            .fillMaxSize()
                            .background(Color.Black)
                            .padding(innerPadding)
                    ) {
                        VerticalSlider(modifier = Modifier.align(Alignment.Center))
                    }
                }
            }
        }
    }
}

@Composable
fun VerticalSlider(modifier: Modifier = Modifier) {
    var sliderPosition by remember {
        mutableStateOf(50f)
    }

    val interactionSource = remember {
        MutableInteractionSource()
    }

    val isPressed by interactionSource.collectIsDraggedAsState()

    var currentConfig = LocalConfiguration.current
    var sliderHeight by remember { mutableStateOf(0.dp) }
    var sliderWidth by remember { mutableStateOf(0.dp) }
    val screenWidth = currentConfig.screenWidthDp
    var screenHeight = currentConfig.screenHeightDp
    var density = LocalDensity.current

    val size =
        if (screenWidth < screenHeight) 1.0f else (screenHeight.toFloat() / screenWidth.toFloat() - 0.1f)
    Slider(
        modifier = modifier
            .fillMaxWidth(size)
            .onGloballyPositioned { coordinates ->
                sliderHeight = with(density) { coordinates.size.height.toDp() }
                sliderWidth = with(density) { coordinates.size.width.toDp() }
            }
            .graphicsLayer {
                rotationZ = 270f
            },
        value = sliderPosition,
        onValueChange = {
            sliderPosition = it
        },
        valueRange = 0f..100f,
        interactionSource = interactionSource,
    )

    if (isPressed) {
        Box(modifier = Modifier
            .fillMaxSize()
            .offset(
                x = sliderHeight,
                y = sliderWidth / 2 - (sliderWidth * (sliderPosition / 100))
            )
            .drawBehind {
                drawCircle(
                    brush = Brush.radialGradient(
                        0.0f to Color.Green,
                        0.25f to Color.White,
                        1.0f to Color.Black.copy(alpha = 0.25f)
                    ),
                    center = center,
                    radius = sliderPosition
                )
            }) {
            Text(
                modifier = Modifier
                    .offset(
                        x = sliderHeight,
                        y = sliderHeight * (sliderPosition / 100)
                    )
                    .align(Alignment.Center),
                text = "$sliderPosition", color = Color.White, fontSize = 25.sp
            )
        }
    }
}

Hope this was useful.