Search code examples
javaandroidkotlinviewviewgroup

create View with curved edge and rounded corners in android


I am trying to make a custom view in android like in the picture with curve edges and rounded corners. How to achieve this?

enter image description here


Solution

  • I've tried to create a custom view for this (squircle) shape a while ago. Although it's not complete, it'll give you a basic idea on how to draw such shapes. By the way you'll need to disable clipChildren of its parent view to fix clipping.

    package com.certainlyaria.squircle
    
    import android.content.Context
    import android.graphics.*
    import android.util.AttributeSet
    import android.view.View
    
    
    class SquircleView @JvmOverloads constructor(
        context: Context,
        attrs: AttributeSet? = null,
        defStyleAttr: Int = 0
    ) : View(context, attrs, defStyleAttr) {
        private val paint = Paint().apply {
            color = Color.MAGENTA
            isAntiAlias = true
            style = Paint.Style.STROKE
            strokeJoin = Paint.Join.ROUND
            strokeWidth = 10f
        }
    
        companion object {
            private const val CURVE = 75f
        }
    
        private val clipPath = Path()
    
        private var smooth = Path()
    
        private val clipRect = RectF(
            CURVE, CURVE, 0f, 0f
        )
    
        override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
            super.onSizeChanged(w, h, oldw, oldh)
    
            clipRect.apply {
                right = w - CURVE
                bottom = h - CURVE
            }
            clipPath.apply {
                rewind()
                moveTo(0f, (width) / 2f)
                cubicTo(
                    0f,
                    0f,
                    (width) / 4f,
                    0f,
                    (width) / 2f,
                    0f
                )
                cubicTo(
                    (width) * 3 / 4f,
                    0f,
                    width.toFloat(),
                    0f,
                    width.toFloat(),
                    width / 2f
                )
                cubicTo(
                    width.toFloat(),
                    width.toFloat(),
                    width * 3f / 4,
                    width.toFloat(),
                    (width) / 2f,
                    width.toFloat()
                )
                cubicTo(
                    width / 4f,
                    width.toFloat(),
                    0f,
                    width.toFloat(),
                    0f,
                    (width) / 2f
                )
            }
    
            smooth = getSquirclePaath(0, 0, width / 2)
        }
    
        override fun onDraw(canvas: Canvas) {
            canvas.save()
            canvas.drawPath(clipPath, paint)
            //canvas.drawPath(smooth, paint)
            canvas.restore()
        }
    
        private fun getSquirclePaath(
            left: Int,
            top: Int,
            radius: Int
        ): Path { //Formula: (|x|)^3 + (|y|)^3 = radius^3
            val radiusToPow = radius * radius * radius.toDouble()
            val path = Path()
            path.moveTo((-radius).toFloat(), 0f)
            for (x in -radius..radius) path.lineTo(
                x.toFloat(),
                Math.cbrt(radiusToPow - Math.abs(x * x * x)).toFloat()
            )
            for (x in radius downTo -radius) path.lineTo(
                x.toFloat(),
                (-Math.cbrt(radiusToPow - Math.abs(x * x * x))).toFloat()
            )
            path.close()
            val matrix = Matrix()
            matrix.postTranslate((left + radius).toFloat(), (top + radius).toFloat())
            path.transform(matrix)
            return path
        }
    }