quick q, is there a easy way to make sure a border...
# compose
a
quick q, is there a easy way to make sure a border is drawn outside of the box in compose
I know order matters and such, but borders are still drawn inside of the box
c
cc @Nader Jawad
a
Just for context
n
Borders right now are implemented as interior strokes. You could probably achieve a similar effect by growing the content and drawing a border that way using padding
a
Even if its fillMaxWidth?
n
Yes so you can either make a custom size modifier that adds the border width or grow the corresponding container by the border width as well and use fillMaxWidth
a
Gotcha 🙂
n
A future version of compose will more than likely expose a parameter to specify an interior, center or exterior stroke directly on the border modifier API and make this a bit easier. No ETA on this unfortunately
c
Yeah that would be great to have since that would align better with how borders are specified from designers
c
@andrew I basically have to make the same thing now. How'd you go about this? I'd love to be able to just add a custom clip modifier to that lock icon that knows how to clip/mask the wifi logo. lol
seems like thats not possible though?
a
It's just baked into the icon itself, nothing special or dynamic about it
n
In the meantime you can enlarge the size of the composable to incorporate the width of the border if you want an exterior/centered border
a
I just want to clarify real quick when I say it's baked into the icon itself, I mean the lock is baked into the icon, but the backdrop is separate, and is a box
And the outer border for the container, I have a separate modifier for 🙂
n
If you want to mask icons you can do a similar strategy that was done on the thread for masking out circular profile images in this thread https://kotlinlang.slack.com/archives/CJLTWPH7S/p1622156832115600?thread_ts=1622125126.047600&cid=CJLTWPH7S
c
@Nader Jawad yeah I tried that snippet, but in this case I need the mask/clipped part to change sizes as my item changes size and so if I could just use some imaginary api of
.border(1.dp, BorderStyle.Clip)
on my icon it'd be clutch. And thats just because the
Copy code
drawCircle(
                Color.Black,
                size.minDimension / 2,
                size.center,
                style = stroke,
                blendMode = BlendMode.Clear
            )
doesn't scale correctly with my image. While a border works just fine if I set the border to white. But if I use a different background color then the effect is broken. 😅
n
Do you have a mock/screenshot of what you are trying to build? Generally speaking you can mask out content by leveraging an off screen layer with corresponding blend modes.
c
I can DM you the mock
n
Just fyi here's another example that shows how to apply a similar masking technique to add a badge to an icon (or any composable)
Copy code
Box(modifier = Modifier.fillMaxSize()
        .wrapContentSize(Alignment.Center)
        // Leverage an offscreen rasterization of the box composable so we can use use the clear
        // blend mode to erase/mask out some pixels without clearing the original destination pixels
        .graphicsLayer{ compositingStrategy = CompositingStrategy.Offscreen }
    ) {
        Image(
            Icons.Outlined.AccountCircle,
            "ProfileImage",
            Modifier.size(48.dp).padding(top = 5.dp),
            contentScale = ContentScale.FillBounds
        )
        Text(text = "2",
            color = Color.White,
            textAlign = TextAlign.Center,
            modifier = Modifier.align(Alignment.TopEnd).size(20.dp).drawWithContent {
            // Color doesn't matter here but clear out a circle of pixels slightly larger
            // than the area of the text composable
            drawCircle(color = Color.Black, blendMode = BlendMode.Clear, radius = this.size.minDimension / 2 + 5f)
            // Draw a red background circle smaller than the area that was masked out above
            drawCircle(color = Color.Red)
            drawContent()
        })
    }
This generates the following: