androidxmlandroid-shapedrawable

Custom border layout contains half of a circle


I need create xml with two layout title and description. In title layout I need add border have half of circle in bottom left and right, and with description layout border have half of circle in top left and right. Here is my design

enter image description here

I can do it with create two half circle over line of rectangle radius border, but I don't want use this. How I can do it with another solution? Please give me key work or solution to do it! Thank you so much!


Solution

  • You can use the ShapeAppearanceModel defining a custom CornerTreatment to apply to the components. Something like:

        val radius = resources.getDimension(R.dimen.default_corner_radius)
        val title_layout = findViewById<LinearLayout>(R.id.title_layout)
        
        val titleShapeModel = ShapeAppearanceModel().toBuilder()
                .setTopLeftCorner(CornerFamily.ROUNDED, radius)
                .setTopRightCorner(CornerFamily.ROUNDED, radius)
                .setBottomLeftCorner(ConcaveRoundedCornerTreatment()).setBottomLeftCornerSize(radius)
                .setBottomRightCorner(ConcaveRoundedCornerTreatment()).setBottomRightCornerSize(radius)
                .build()
        val titleBackground = MaterialShapeDrawable(titleShapeModel)
        titleBackground.setStroke(1f, ContextCompat.getColor(this, R.color.colorPrimaryDark))
    
        ViewCompat.setBackground(title_layout, titleBackground)
    

    where the ConcaveRoundedCornerTreatment is:

    class ConcaveRoundedCornerTreatment : CornerTreatment() {
    
        override fun getCornerPath(
                shapePath: ShapePath,
                angle: Float,
                interpolation: Float,
                radius: Float
        ) {
            val interpolatedRadius = radius * interpolation
            shapePath.reset(0f, interpolatedRadius, ANGLE_LEFT, ANGLE_LEFT - angle)
            shapePath.addArc(
                    -interpolatedRadius,
                    -interpolatedRadius,
                    interpolatedRadius,
                    interpolatedRadius,
                    ANGLE_BOTTOM,
                    -angle
            )
        }
    
        companion object {
            const val ANGLE_LEFT = 180f
            const val ANGLE_BOTTOM = 90f
        }
    }
    

    Just do the same with the description layout:

    enter image description here

    If you are using a view like a CardView which has a built-in shapeAppearanceModel:

    cardView.shapeAppearanceModel = cardView.shapeAppearanceModel.toBuilder()
            .setTopRightCorner(concaveRoundedCornerTreatment).
            .........
            .build()