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.

