In this post I will show you how I created a vertical slider in Compose for Android.
The root element is still the Slider Composable but we will just 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.
During the change of the Slider position, I created a simple dot and Text to follow the location of the slider.
I created variables to hold the size of the slider for my use case. You may not need this either. You could create a fixed size.
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
)
}
}
}

Leave a Reply