android-jetpack-composeuiswitch

Jetpack compose Switch() TrackWidth, TrackStrokeWidth, ThumbDiameter


Maybe someone can tell me how to set in Switch() size for TrackWidth, TrackStrokeWidth, ThumbDiameter

                Switch(
                modifier = Modifier
                    .padding(end=16.dp),
                checked = auto.mainAuto.value,
                onCheckedChange = { auto.mainAuto.value = it },
                colors = SwitchDefaults.colors(
                    checkedThumbColor = white_white,
                    checkedTrackColor = Accent_Blue,
                    uncheckedThumbColor = white_white,
                    uncheckedTrackColor = Disabled_Text,
                    ),
            )

Solution

  • As of Jetpack Compose 1.0.4, you cannot change them. But, the good news is that you can easily create any type of switch using Canvas API.

    For example:

    enter image description here enter image description here

    This is the code:

    import android.os.Bundle
    import androidx.activity.ComponentActivity
    import androidx.activity.compose.setContent
    import androidx.compose.animation.core.animateFloatAsState
    import androidx.compose.foundation.Canvas
    import androidx.compose.foundation.gestures.detectTapGestures
    import androidx.compose.foundation.layout.*
    import androidx.compose.material.MaterialTheme
    import androidx.compose.material.Surface
    import androidx.compose.material.Text
    import androidx.compose.runtime.Composable
    import androidx.compose.runtime.mutableStateOf
    import androidx.compose.runtime.remember
    import androidx.compose.ui.Alignment
    import androidx.compose.ui.Modifier
    import androidx.compose.ui.draw.scale
    import androidx.compose.ui.geometry.CornerRadius
    import androidx.compose.ui.geometry.Offset
    import androidx.compose.ui.graphics.Color
    import androidx.compose.ui.graphics.drawscope.Stroke
    import androidx.compose.ui.input.pointer.pointerInput
    import androidx.compose.ui.platform.LocalDensity
    import androidx.compose.ui.tooling.preview.Preview
    import androidx.compose.ui.unit.Dp
    import androidx.compose.ui.unit.dp
    
    /*
    For more designs with source code, visit: https://semicolonspace.com/jetpack-compose-samples/
     */
    
    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                BlogPostsTheme(darkTheme = false) {
                    Surface(
                        modifier = Modifier.fillMaxSize(),
                        color = MaterialTheme.colors.background
                    ) {
                        Column(
                            modifier = Modifier.fillMaxSize(),
                            verticalArrangement = Arrangement.Center,
                            horizontalAlignment = Alignment.CenterHorizontally
                        ) {
                            Switch2()
                        }
                    }
                }
            }
        }
    }
    
    @Composable
    fun Switch2(
        scale: Float = 2f,
        width: Dp = 36.dp,
        height: Dp = 20.dp,
        strokeWidth: Dp = 2.dp,
        checkedTrackColor: Color = Color(0xFF35898F),
        uncheckedTrackColor: Color = Color(0xFFe0e0e0),
        gapBetweenThumbAndTrackEdge: Dp = 4.dp
    ) {
    
        val switchON = remember {
            mutableStateOf(true) // Initially the switch is ON
        }
    
        val thumbRadius = (height / 2) - gapBetweenThumbAndTrackEdge
    
        // To move thumb, we need to calculate the position (along x axis)
        val animatePosition = animateFloatAsState(
            targetValue = if (switchON.value)
                with(LocalDensity.current) { (width - thumbRadius - gapBetweenThumbAndTrackEdge).toPx() }
            else
                with(LocalDensity.current) { (thumbRadius + gapBetweenThumbAndTrackEdge).toPx() }
        )
    
        Canvas(
            modifier = Modifier
                .size(width = width, height = height)
                .scale(scale = scale)
                .pointerInput(Unit) {
                    detectTapGestures(
                        onTap = {
                            // This is called when the user taps on the canvas
                            switchON.value = !switchON.value
                        }
                    )
                }
        ) {
            // Track
            drawRoundRect(
                color = if (switchON.value) checkedTrackColor else uncheckedTrackColor,
                cornerRadius = CornerRadius(x = 10.dp.toPx(), y = 10.dp.toPx()),
                style = Stroke(width = strokeWidth.toPx())
            )
    
            // Thumb
            drawCircle(
                color = if (switchON.value) checkedTrackColor else uncheckedTrackColor,
                radius = thumbRadius.toPx(),
                center = Offset(
                    x = animatePosition.value,
                    y = size.height / 2
                )
            )
        }
    
        Spacer(modifier = Modifier.height(18.dp))
    
        Text(text = if (switchON.value) "ON" else "OFF")
    }
    

    Edit:

    Instead of Canvas, you can also use Box.