5

I need to draw a rounded square, something like drawRoundRect, but only the outline.

something like this.

enter image description here

this image is drawn by hand, as I said I need it to look like drawRoundRect but without outline (I don't want it to look hand drawn)

If you see it, the line has a gradient like this: red -> white -> red

I need that same gradient. If anyone has an idea or a solution I would greatly appreciate it.

Thracian
  • 43,021
  • 16
  • 133
  • 222
chrrissoft
  • 149
  • 1
  • 10

1 Answers1

7

You can draw it like this

Column(modifier = Modifier
    .fillMaxSize()
    .background(Color.Black)) {
    val gradient = Brush.radialGradient(
        listOf(Color.Red.copy(.3f), Color.Red, Color.Red.copy(.3f)),
        center = Offset(300f,300f),
        radius = 500f
    )

    Canvas(modifier = Modifier.fillMaxSize()) {
        drawRoundRect(
            gradient,
            topLeft = Offset(100f, 100f),
            size = Size(400f, 400f),
            cornerRadius = CornerRadius(5.dp.toPx(), 5.dp.toPx()),
            style = Stroke(width = 6.dp.toPx())
        )
        drawRoundRect(
            Color.White,
            topLeft = Offset(100f, 100f),
            size = Size(400f, 400f),
            cornerRadius = CornerRadius(5.dp.toPx(), 5.dp.toPx()),
            style = Stroke(width = 2.dp.toPx())
        )
    }
}

This one will look better

@Composable
private fun NeonSample() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Black)
    ) {

        val paint = remember {
            Paint().apply {
                style = PaintingStyle.Stroke
                strokeWidth = 30f
            }
        }

        val frameworkPaint = remember {
            paint.asFrameworkPaint()
        }

        val color = Color.Red


        Canvas(modifier = Modifier.fillMaxSize()) {
            this.drawIntoCanvas {

                val transparent = color
                    .copy(alpha = 0f)
                    .toArgb()

                frameworkPaint.color = transparent

                frameworkPaint.setShadowLayer(
                    10f,
                    0f,
                    0f,
                    color
                        .copy(alpha = .5f)
                        .toArgb()
                )

                it.drawRoundRect(
                    left = 100f,
                    top = 100f,
                    right = 500f,
                    bottom = 500f,
                    radiusX = 5.dp.toPx(),
                    5.dp.toPx(),
                    paint = paint
                )

                drawRoundRect(
                    Color.White,
                    topLeft = Offset(100f, 100f),
                    size = Size(400f, 400f),
                    cornerRadius = CornerRadius(5.dp.toPx(), 5.dp.toPx()),
                    style = Stroke(width = 2.dp.toPx())
                )


                frameworkPaint.setShadowLayer(
                    30f,
                    0f,
                    0f,
                    color
                        .copy(alpha = .5f)
                        .toArgb()
                )


                it.drawRoundRect(
                    left = 600f,
                    top = 100f,
                    right = 1000f,
                    bottom = 500f,
                    radiusX = 5.dp.toPx(),
                    5.dp.toPx(),
                    paint = paint
                )

                drawRoundRect(
                    Color.White,
                    topLeft = Offset(600f, 100f),
                    size = Size(400f, 400f),
                    cornerRadius = CornerRadius(5.dp.toPx(), 5.dp.toPx()),
                    style = Stroke(width = 2.dp.toPx())
                )
            }
        }
    }
}

enter image description here

Edit

Full size rounded rectangle. You can remove inset if you don't want to have padding for Canvas

@Composable
private fun NeonSample() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(Color.Black)
    ) {

        val paint = remember {
            Paint().apply {
                style = PaintingStyle.Stroke
                strokeWidth = 30f
            }
        }

        val frameworkPaint = remember {
            paint.asFrameworkPaint()
        }

        val color = Color.Red

        val transparent = color
            .copy(alpha = 0f)
            .toArgb()

        frameworkPaint.color = transparent

        frameworkPaint.setShadowLayer(
            10f,
            0f,
            0f,
            color
                .copy(alpha = .5f)
                .toArgb()
        )


        Canvas(modifier = Modifier.fillMaxSize()) {
           inset(10.dp.toPx()){
               this.drawIntoCanvas {
                   it.drawRoundRect(
                       left = 0f,
                       top = 0f,
                       right = size.width,
                       bottom = size.height,
                       radiusX = 5.dp.toPx(),
                       5.dp.toPx(),
                       paint = paint
                   )

                   drawRoundRect(
                       Color.White,
                       cornerRadius = CornerRadius(5.dp.toPx(), 5.dp.toPx()),
                       style = Stroke(width = 2.dp.toPx())
                   )
               }
           }
        }
    }
}
Thracian
  • 43,021
  • 16
  • 133
  • 222
  • Thank you very much. I would like to know how to make [Drawroungerect](https://developer.android.com/reference/kotlin/androidx/compose/ui/graphics/Canvas#drawRoundRect(kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,kotlin.Float,androidx.compose.ui.graphics.Paint)) adjust to the entire size of the content. that is not having to pass calculated values. Do you know how to do that? – chrrissoft Jul 15 '22 at 05:05
  • How can we make borders of a button or a card to have like these neon effects? – Reza Zeraati Nov 04 '22 at 17:31