David Ibrahim
David Ibrahim

Reputation: 3227

How to have dashed border in Jetpack Compose?

I can easily create a normal border using the Modifier.border() but how to create a dashed border as shown in the image below.

enter image description here

Upvotes: 46

Views: 17031

Answers (4)

Boken
Boken

Reputation: 5446

@Composable
private fun AddNewFileButton(
    modifier: Modifier = Modifier,
    onClick: () -> Unit,
) {
    val stroke = Stroke(
        width = 4f,
        pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
    )

    Box(
        modifier = modifier
            .drawBehind {
                drawRoundRect(
                    color = Color.Blue,
                    style = stroke,
                    cornerRadius = CornerRadius(16.dp.toPx())
                )
            }
            .clip(RoundedCornerShape(16.dp))
            .clickable { onClick() },
    ) {
        Row(
            modifier = modifier.padding(16.dp),
            horizontalArrangement = Arrangement.Center
        ) {
            Text(
                text = "Add new item"
            )
        }
    }
}

enter image description here

Upvotes: 5

Gabriele Mariotti
Gabriele Mariotti

Reputation: 363469

There isn't a parameter in Modifier.border() to achieve a dashed path.

However you can use a DrawScope to draw a dashed Path using PathEffect.dashPathEffect.

Something like:

val stroke = Stroke(width = 2f,
    pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
)

You can draw it using the drawBehind modifier:

Box(
    Modifier
        .size(250.dp,60.dp)
        .drawBehind {
            drawRoundRect(color = Color.Red, style = stroke)
        },
    contentAlignment = Alignment.Center
) {
    Text(textAlign = TextAlign.Center,text = "Tap here to introduce yourseft")
}

enter image description here

If you want rounded corner just use the cornerRadius attribute in the drawRoundRect method:

drawRoundRect(color = Color.Red,style = stroke, cornerRadius = CornerRadius(8.dp.toPx()))

enter image description here


If you prefer you can build your custom Modifier with the same code above. Something like:

fun Modifier.dashedBorder(strokeWidth: Dp, color: Color, cornerRadiusDp: Dp) = composed(
    factory = {
        val density = LocalDensity.current
        val strokeWidthPx = density.run { strokeWidth.toPx() }
        val cornerRadiusPx = density.run { cornerRadiusDp.toPx() }

        this.then(
            Modifier.drawWithCache {
                onDrawBehind {
                    val stroke = Stroke(
                        width = strokeWidthPx,
                        pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
                    )

                    drawRoundRect(
                        color = color,
                        style = stroke,
                        cornerRadius = CornerRadius(cornerRadiusPx)
                    )
                }
            }
        )
    }
)

and then just apply it:

Box(
    Modifier
        .size(250.dp,60.dp)
        .dashedBorder(1.dp, Red, 8.dp),
    contentAlignment = Alignment.Center
) {
    Text(
        text = "Tap here to introduce yourself",
        textAlign = TextAlign.Center,
    )
}

Upvotes: 76

hosseinAmini
hosseinAmini

Reputation: 2342

I wrote this extension for the Modifier you can simply use it or modify it.

fun Modifier.dashedBorder(width: Dp, radius: Dp, color: Color) = 
    drawBehind {
        drawIntoCanvas {
            val paint = Paint()
                .apply {
                    strokeWidth = width.toPx()
                    this.color = color
                    style = PaintingStyle.Stroke
                    pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
        }
        it.drawRoundRect(
            width.toPx(),
            width.toPx(),
            size.width - width.toPx(),
            size.height - width.toPx(),
            radius.toPx(),
            radius.toPx(),
            paint
        )
    }
}

Upvotes: 15

David Ibrahim
David Ibrahim

Reputation: 3227

After some digging in the normal border modifier, I found out that it uses Stroke object which can take a parameter PathEffect that can make it dashed, here is a modified version of the normal border function that takes this parameter.

https://gist.github.com/DavidIbrahim/236dadbccd99c4fd328e53587df35a21

Upvotes: 19

Related Questions