Dial Basics
The Dial composable is the core component of ChromaDial. It provides a circular draggable control that users can interact with by dragging around its circumference.
Basic Usage
Section titled “Basic Usage”var degree by remember { mutableFloatStateOf(0f) }
Dial( degree = degree, onDegreeChanged = { degree = it }, modifier = Modifier.size(200.dp), startDegrees = 0f, sweepDegrees = 360f,)API Variants
Section titled “API Variants”ChromaDial provides two overloaded versions of the Dial composable:
Simple API (startDegrees + sweepDegrees)
Section titled “Simple API (startDegrees + sweepDegrees)”Use this when you want to define an arc starting from a specific angle:
Dial( degree = degree, onDegreeChanged = { degree = it }, startDegrees = 270f, // Start at 9 o'clock position sweepDegrees = 180f, // Sweep 180 degrees (half circle))Advanced API (degreeRange)
Section titled “Advanced API (degreeRange)”Use this for precise control over the allowed rotation range:
Dial( degree = degree, onDegreeChanged = { degree = it }, degreeRange = 135f..405f, // Custom range)Parameters
Section titled “Parameters”degree
Section titled “degree”Type: Float
The current rotation angle of the dial in degrees. This is the controlled state value that determines where the thumb is positioned.
0fpoints upward (12 o’clock)90fpoints right (3 o’clock)180fpoints down (6 o’clock)270fpoints left (9 o’clock)
var degree by remember { mutableFloatStateOf(90f) } // Start at 3 o'clockonDegreeChanged
Section titled “onDegreeChanged”Type: (Float) -> Unit
Callback invoked when the user drags the dial. Update your state in this callback:
onDegreeChanged = { newDegree -> degree = newDegree }modifier
Section titled “modifier”Type: Modifier
Default: Modifier
Standard Compose modifier for sizing and positioning the dial. The dial’s radius is calculated from the modifier’s constraints.
modifier = Modifier.size(200.dp) // 200dp diameter dialFor non-square dials (like semi-circles), use different width and height:
modifier = Modifier.size(200.dp, 100.dp) // Semi-circlestartDegrees
Section titled “startDegrees”Type: Float
The starting angle of the allowed rotation range. Used with sweepDegrees.
0f- Top (12 o’clock)90f- Right (3 o’clock)180f- Bottom (6 o’clock)270f- Left (9 o’clock)
startDegrees = 270f // Start at 9 o'clocksweepDegrees
Section titled “sweepDegrees”Type: Float
How many degrees the dial can sweep from the start position. Used with startDegrees.
startDegrees = 270f,sweepDegrees = 180f, // Creates a top semi-circle (270° to 450°/90°)degreeRange
Section titled “degreeRange”Type: ClosedFloatingPointRange<Float>
Default: 0f..360f
Alternative to startDegrees/sweepDegrees. Defines the exact range of allowed rotation.
degreeRange = 0f..360f // Full circledegreeRange = 135f..405f // 270 degree arcdegreeRange = -360f..360f // Two full rotations allowedradiusMode
Section titled “radiusMode”Type: RadiusMode
Default: RadiusMode.WIDTH
Determines how the dial’s radius is calculated from its constraints:
RadiusMode.WIDTH- Radius = half the widthRadiusMode.HEIGHT- Radius = half the height
radiusMode = RadiusMode.HEIGHT // Use height for radius calculationThis is useful for non-square dials where you want the thumb to follow a specific dimension.
Type: Int
Default: 0
Number of discrete snap points between the start and end of the range. When 0, the dial rotates continuously (smooth rotation).
steps = 0 // Continuous rotation (no snapping)steps = 10 // 11 snap points (start + 10 steps + end = 12 positions)The formula for total positions is: steps + 2 (includes start and end positions).
onValueChangeFinished
Section titled “onValueChangeFinished”Type: (() -> Unit)?
Default: null
Callback invoked when the user finishes dragging (lifts their finger/releases mouse). Useful for committing changes or triggering actions.
onValueChangeFinished = { saveSettings(degree)}interactionSource
Section titled “interactionSource”Type: MutableInteractionSource
Default: remember { MutableInteractionSource() }
Allows observing and customizing interactions (drag, hover). Useful for adding visual feedback during interaction.
val interactionSource = remember { MutableInteractionSource() }val isDragging by interactionSource.collectIsDraggedAsState()
Dial( interactionSource = interactionSource, // ... other params)
// isDragging is true while user is draggingType: @Composable (DialState) -> Unit
Custom composable for the draggable handle. Receives DialState with information about the dial’s current state.
thumb = { state -> Box( Modifier .size(32.dp) .background(Color.Blue, CircleShape) )}See Customization for advanced examples.
Type: @Composable (DialState) -> Unit
Custom composable for the background track. Receives DialState to draw progress arcs or tick marks.
track = { state -> Box( Modifier .fillMaxSize() .drawBehind { drawCircle( color = Color.Gray, style = Stroke(width = 8.dp.toPx()), radius = state.radius - 4.dp.toPx() ) } )}Common Patterns
Section titled “Common Patterns”Full Circle Dial
Section titled “Full Circle Dial”Dial( degree = degree, onDegreeChanged = { degree = it }, modifier = Modifier.size(200.dp), startDegrees = 0f, sweepDegrees = 360f,)Semi-Circle (Top Arc)
Section titled “Semi-Circle (Top Arc)”Dial( degree = degree, onDegreeChanged = { degree = it }, modifier = Modifier.size(200.dp, 100.dp), startDegrees = 270f, sweepDegrees = 180f,)Stepped Selector (like a camera mode dial)
Section titled “Stepped Selector (like a camera mode dial)”Dial( degree = animatedDegree, // Use animation for smooth snapping onDegreeChanged = { degree = it }, modifier = Modifier.size(200.dp), startDegrees = -90f, sweepDegrees = 220f, steps = 10, // 12 selectable positions)Multi-Rotation (like a timer)
Section titled “Multi-Rotation (like a timer)”Dial( degree = degree, onDegreeChanged = { degree = it }, modifier = Modifier.size(300.dp), startDegrees = -360f * 4, // Allow 4 counter-clockwise rotations sweepDegrees = 360f * 8, // Total 8 rotations range steps = (60 * 4) - 1, // Snap every minute)Next Steps
Section titled “Next Steps”- Customization - Create custom thumb and track designs
- DialState Reference - Understand the state object