Reputation: 539
I want to explicitly retrieve the value of the fillMaxSize()
.
Suppose i have:
Box(Modifier
.fillMaxSize()
.background(Color.Yellow))
{
var size = ?
Box(Modifier
.size(someSize)
.background(Color.Blue))
{Text("Test")}
I want to change the size of my second Box multiple times (will probably stem from some viewmodel) and then reset it to maxSize.
How can I do that? I don't know any 'getMaxSize()'-method?
Upvotes: 37
Views: 56413
Reputation: 4030
Take a look at BoxWithConstraints
:
@Composable
fun Card(/* ... */) {
BoxWithConstraints {
if (maxWidth < 400.dp) {
Column {
//...
}
} else {
Row{
//...
}
}
}
}
It gives you a maxWidth
and a maxHeight
to create your logic. More info here on this Android Docs.
Hope it helps!
Upvotes: 5
Reputation: 87605
If you really need the raw size value, you can use the following code:
var size by remember { mutableStateOf(IntSize.Zero) }
Box(Modifier
.fillMaxSize()
.background(Color.Yellow)
.onSizeChanged {
size = it
}
) {
Box(
Modifier
.then(
with(LocalDensity.current) {
Modifier.size(
width = size.width.toDp(),
height = size.height.toDp(),
)
}
)
.background(Color.Blue)
) { Text("Test") }
}
But note, that it's not optimal in terms of performance: this view gets rendered two times. First time second box gets size zero, then the onSizeChanged
block gets called, and then view gets rendered for the second time.
Be especially careful if using remember
in top level views, because changing state will trigger full view stack re-render. Usually you want split your screen into views with states, so changing one view state only will re-render this view.
Also you can use BoxWithConstraints
where you can get maxWidth
/maxHeight
inside the BoxWithConstraintsScope
: it's much less code and a little better on performance.
BoxWithConstraints(
Modifier
.fillMaxSize()
.background(Color.Yellow)
) {
Box(
Modifier
.size(
width = maxWidth,
height = maxHeight,
)
.background(Color.Blue)
) { Text("Test") }
}
But usually if you wanna indicate size dependencies, using modifiers without direct knowing the size should be enough. It's more "Compose" way of writing code and more optimized one.
So if you wanna you second box be same size as the first one, just use .fillMaxSize()
on it too. If you wanna it to be some part of the parent, you can add fraction param. To make second box size be half size of the first one, you do:
Box(
Modifier
.fillMaxSize(fraction = 0.5f)
) { Text("Test") }
If you wanna different parts for width/height:
Box(
Modifier
.fillMaxWidth(fraction = 0.3f)
.fillMaxHeight(fraction = 0.7f)
) { Text("Test") }
Upvotes: 63
Reputation: 1284
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
var parentSize by remember {
mutableStateOf(Size.Zero)
}
Box(
modifier = Modifier
.fillMaxWidth()
.aspectRatio(1f)
.background(Color.Green)
) {
Box(
modifier = Modifier
.size(100.dp)
.align(Alignment.Center)
.background(Color.Red)
.onGloballyPositioned {
//here u can access the parent layout coordinate size
parentSize = it.parentLayoutCoordinates?.size?.toSize()?: Size.Zero
}
) {
Column(Modifier.fillMaxSize()) {
Text(text = "parent size = $parentSize")
}
}
}
}
Upvotes: 1
Reputation: 363429
In your first Box
you can use the onGloballyPositioned
modifier to get the size
.
It is called with the final LayoutCoordinates
of the Layout when the global position of the content may have changed.
Then use coordinates.size
to get the size of the first Box
.
var size by remember { mutableStateOf(Size.Zero)}
Box(
Modifier
.fillMaxSize()
.background(Color.Yellow)
.onGloballyPositioned { coordinates ->
size = coordinates.size.toSize()
}
Box(){ /*....*/ }
)
Upvotes: 25