Hoa.Tran
Hoa.Tran

Reputation: 935

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!

Upvotes: 3

Views: 284

Answers (1)

Gabriele Mariotti
Gabriele Mariotti

Reputation: 363905

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()

Upvotes: 3

Related Questions