7

I am trying to prepare a design in jetpack compose with a partial border on one side of the box. Here is the UI I have right now,

The background is a solid color as of now but will be replaced with a image. I want to break border on bottom left of and add some text similar to the screenshot below while keeping the background as it is.

Here is my code:

Box(modifier = Modifier
    .fillMaxWidth()
    .fillMaxHeight()) {
    Box(modifier = Modifier.fillMaxHeight().fillMaxWidth().background(Color(0xFF37C7D7).copy(alpha = 0.6f)))
    Box(modifier = Modifier
        .fillMaxHeight()
        .fillMaxWidth()
        .background(Color.Transparent)
        .padding(20.dp,30.dp)
        .border(width = 0.8.dp, color = Color.White.copy(alpha = 0.5f), shape=RoundedCornerShape(32.dp))
    )
    Box(modifier = Modifier
        .fillMaxHeight()
        .fillMaxWidth()
        .background(Color.Transparent)
        .padding(28.dp,38.dp)
        .border(width = 0.8.dp, color = Color.White.copy(alpha = 0.5f), shape=RoundedCornerShape(28.dp))
    )
    Column(modifier = Modifier.statusBarsPadding()
        .fillMaxWidth()
        .fillMaxHeight().padding(20.dp,40.dp),
        verticalArrangement = Arrangement.Bottom) {
        Text(text = "this is Test",modifier = Modifier.padding(0.dp,30.dp))
    }
}

1 Answer 1

14

You can prevent part of the view from being drawn with Modifier.drawWithContent and DrawScope.clipRect. Using this method, you can create the following modifier:

fun Modifier.drawWithoutRect(rect: Rect?) =
    drawWithContent {
        if (rect != null) {
            clipRect(
                left = rect.left,
                top = rect.top,
                right = rect.right,
                bottom = rect.bottom,
                clipOp = ClipOp.Difference,
            ) {
                [email protected]()
            }
        } else {
            drawContent()
        }
    }

Use it like this:

Box(
    modifier = Modifier
        .fillMaxWidth()
        .fillMaxHeight()
) {
    Image(
        painterResource(id = R.drawable.my_image),
        contentDescription = null,
        contentScale = ContentScale.FillBounds,
        modifier = Modifier.fillMaxSize()
    )
    var textCoordinates by remember { mutableStateOf<Rect?>(null) }
    Box(
        modifier = Modifier
            .fillMaxHeight()
            .fillMaxWidth()
            .background(Color(0xFF37C7D7).copy(alpha = 0.6f))
    )
    Box(
        modifier = Modifier
            .fillMaxHeight()
            .fillMaxWidth()
            .drawWithoutRect(textCoordinates)
            .padding(20.dp, 30.dp)
            .border(
                width = 0.8.dp,
                color = Color.White.copy(alpha = 0.5f),
                shape = RoundedCornerShape(32.dp)
            )
    )
    Box(
        modifier = Modifier
            .fillMaxHeight()
            .fillMaxWidth()
            .drawWithoutRect(textCoordinates)
            .padding(28.dp, 38.dp)
            .border(
                width = 0.8.dp,
                color = Color.White.copy(alpha = 0.5f),
                shape = RoundedCornerShape(28.dp)
            )
    )
    Column(
        verticalArrangement = Arrangement.Bottom,
        modifier = Modifier
            .statusBarsPadding()
            .padding(20.dp, 40.dp)
            .onGloballyPositioned {
                textCoordinates = it.boundsInParent()
            }
            .align(Alignment.BottomStart)
    ) {
        Text(text = "this is Test", modifier = Modifier.padding(0.dp, 30.dp))
    }
}

Result:

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.