2

For a background element, I'm trying to simply draw a very large filled circle that is offset so that only part of it shows at the bottom. I've got it working to show the circle with an offset, but it seems to only be allowing a max width/height of the parent view, rather than the full size of the circle.

For instance, I have the code below which shows the circle, but changing the size to something like 1000 I would think should make it much larger and span across the bottom of the screen better (needing this to match our designs), but it doesn't; it preserves the size:

Canvas(modifier = Modifier
    .size(516.dp)
    .offset(x = (-190).dp, y = (200).dp)
    .align(alignment = Alignment.BottomStart),
    onDraw = {
        drawCircle(color = Color.DarkGray)
    }
)

Once I hit around 400dp (which is about the width of my screen), it simply won't get larger when I increase further. Is there a way to tell it to ignore the size of the parent view and just span however big I tell it to?

Thracian
  • 43,021
  • 16
  • 133
  • 222
svguerin3
  • 2,433
  • 3
  • 29
  • 53
  • Do you wish to draw a circle with 1000.dp radius inside Canvas? – Thracian May 02 '23 at 17:30
  • @Thracian actually 516.dp is fine, but it's not letting me make it larger than about 400.dp when it hits the width of the screen (it stays the same size as soon as I hit that and try to increase). I need it to be larger to match the designs, as the circle top at the bottom is larger than a size of 400. Hope that makes sense – svguerin3 May 02 '23 at 17:50
  • 1
    Have you set radius for drawCircle. Because by default drawCircle uses `radius: Float = size.minDimension / 2.0f` which is a circle that fills Canvas if you set a fixed size Modifier. And default Composables measure their children composables with max dimensions they have. Let's say if Root Composable is 100.dp you can't create a 200.dp Composable inside default Composables like Row, Column or Box only by using fixed size Modifiers. – Thracian May 02 '23 at 17:56
  • That was it! I simply just needed to set the radius, thank you! Please feel free to add this as an answer, and I will gladly accept. – svguerin3 May 02 '23 at 18:03

1 Answers1

2

First, you can't measure a Composable with size bigger than parnet inside composables like Column, Row, Box without using requiredX or wrapContentX params. That's why you can't create a Composable with 516.dp width while parent Composable has 400.dp width.

The code below won't let Box inside BoxWithConstraints to be 150.dp while parent has 100.dp size.

BoxWithConstraints(modifier = Modifier
        .size(100.dp)
        .border(3.dp, Color.Green)) {
        Box(modifier = Modifier
            .size(150.dp)
            .background(Color.Red))
    }

You can check out this answer for more details.

Second, your Canvas doesn't need to have a size Modifier to draw anything inside it unless you need size or center params. In jetpack Compose you can draw anything outside of a Composable unless you clip your Composable. I posted about size modifiers of Canvas here

How to use IntrinsicSize.Min with canvas in jetpack compose

Drawing inside Canvas with any radius that is set will draw it no matter what that Canvas size is as

@Preview
@Composable
private fun DrawSizeTest() {
    Box(modifier = Modifier.fillMaxSize()) {
        Canvas(modifier = Modifier
            // I posted this to show that size of Canvas doesn't matter
            // If you don't need to use size or center params
            .size(0.dp)
            .offset(x = (-190).dp, y = (200).dp)
            .align(alignment = Alignment.BottomStart),
            onDraw = {
                drawCircle(color = Color.DarkGray, radius = 716.dp.toPx())
            }
        )
    }
}

enter image description here

Thracian
  • 43,021
  • 16
  • 133
  • 222
  • Out of curiosity, what if you're not dealing with a shape with a radius? What if you have an image that you want very-large-sized a particular way and part of it off the screen? Is that possible? – svguerin3 May 02 '23 at 18:24
  • Yes, it is possible. You need to use dstSize and dstOffset to set how big and where you wish to draw an image using ImageBitmap. With painter you can also set size of the Image too `with(painter) { draw(size = Size(100f, 100f))}` – Thracian May 02 '23 at 18:27
  • But need take into consideration that Canvas size effects position of other Composables. Yes, you can draw outside of it but how other sibling Composables are placed depends on dimensions of their siblings and how parent places them such as horizontal or vertical fashion like a Row, Column. – Thracian May 02 '23 at 18:30