I’m applying the same shape for both background an...
# compose
n
I’m applying the same shape for both background and border, but they’re looking incorrect on the corners. Is it a bug?
Copy code
val shape = RoundedCornerShape(8.dp)
    Column(modifier = Modifier.fillMaxSize()) {
        Text(
            text = "Text 1",
            modifier = Modifier.fillMaxWidth()
                .padding(16.dp)
                .drawShadow(2.dp, shape)
                .drawBorder(2.dp, MaterialTheme.colors.secondary, shape)
                .drawBackground(MaterialTheme.colors.primary, shape)
                .padding(16.dp)
        )
    }
👀 4
l
Cc @Nader Jawad
n
The background is drawn as a fill, however, strokes are drawn centered on the shape they are defined in. That is the corner radius of 8.dp defined on the border is centered on the stroke width instead of on the outside corner. If you inset the shape of the background to account for the stroke width, the border should overlap the shape. This is consistent behavior with how Android draws these shapes as well, compose does not change this underlying behavior.
n
yeah… if I do this
Copy code
.drawBorder(2.dp, MaterialTheme.colors.secondary, shape)
.padding(1.dp) // FIX
.drawBackground(MaterialTheme.colors.primary, shape)
It works… But I don’t think this is an expected behavior… If I’m using the same shape with the same size, the last one should overlaps the previous one… 🤷‍♂️ (I don’t know how it works under the hood)
n
I think the border implementation attempts to account for the stroke width by insetting the contents of the border by half of the width. That gets it to draw within the same bounds as the round rect background but as the side effect of not matching the corner radius as the 2dp corner radius is drawn at the center of the stroke which is at a small rect. Cc @matvei maybe we can make some tweaks to border?
Also regarding same shape size, a stroke is always drawn on the outer bounds of the shape that is being drawn so a stroked shape will be larger than the filled in one by half of its stroke width. The the border API leverages Paint.Style.STROKE behind the scenes, while the filled uses Android's Paint.Style.FILL. There is also Paint.Style.FILL_AND_STROKE which will fill in the region while simultaneously draw outside the shape for the stroke width. This is equivalent to drawing twice, one with Paint.Style.FILL and again with Paint.Style.STROKE in a single draw call. We don't expose "fill and stroke" currently in compose as it can cause some confusion.
m
Yeah I can second Nader here. It's an expected behaviour from the implementation side, but shouldn't be from the consumer side. I'm in progress of refactoring
drawBackground
and
drawBorder
to behave more correct and with better default, so
Modifier.drawBorder
will become
Modifier.border
and will properly pad and, probably, clip content inside, so there will be no such problem in the future
👍 3
❤️ 2
n
Thanks @matvei! Good to hear that! 🙂
and thanks for the explanation @Nader Jawad 😉
1
n
@matvei, I am wondering if we can just inset the radius by half the stroke width similar to what we do to inset the shape. By doing so the outside of the stroked shape should match the desired corner radius without making it rounder than it needs to be exposing the pixels underneath