Home > Back-end >  Android Jetpack compose partial border in Box
Android Jetpack compose partial border in Box

Time:10-21

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

CodePudding user response:

You can prevent part of the view from being drawn with Modifier.drawWithContent and 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,
            ) {
                this@drawWithContent.drawContent()
            }
        } 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:

  • Related