Im trying to have a composable scale inside a ConstrainLayout
until a specified max size (usually by setting the .sizeIn
, .widthIn
or .heightIn
Modifier) is reached or the borders of the constraints are reached.
Using only .sizeIn
, .widthIn
or .heightIn
will lead to displaying the composable always at the min size.
So we specify .fillMaxSize
on the composable to take the maximum amount of space (until the specified maxSize). So far so good..
But now when the ConstraintLayout gets smaller for example due to a smaller screen and therefore the borders of the composable are exceeding the constraintborders, the composable isn't scaled down.
That seems understandable because we haven't specified that the size of the composable should orient itself on the borders of the specified constraints. So we specify height = Dimensions.fillToConstraints
and width = Dimensions.fillToConstraints
to only use the space emerging from the given constraints.
And here the problem arises. height = Dimensions.fillToConstraints
and width = Dimensions.fillToConstraints
seem to overwrite the .sizeIn
, .widthIn
or .heightIn
Modifier because now the size of the composable is alway as big as it can be inside the given constraints, not paying attention to the maxWidth
or maxHeight
specified earlier.
A workaround would be to put that composable inside another one for example a box and configure the Modifier like this:
ConstraintLayout {
...
Box(
modifier = Modifier.constrainAs(icon) {
top.linkTo(greeting.bottom) // some composable on top
bottom.linkTo(menuButtons.top) // some composable on bottom
start.linkTo(parent.start)
end.linkTop(parent.end)
height = Dimension.fillToConstraints
width = Dimension.fillToConstraints
}
) {
Icon( // the size responsive composable
imageVector = Icons.Outlined.RequestQuote,
contentDescription = null,
modifier = Modifier
.sizeIn(20.dp, 20.dp, 200.dp, 200.dp) // min and max size
.fillMaxSize()
.align(Alignment.Center)
)
}
...
}
This would give us the desired behavior. But in my opinion the additionally specified box represents a non needed overhead. So my question is:
Is there a way to acquire this behavior without using a secondary composable only using a specific Modifier configuration?
Based on the answer of @hoford who provided me with the idea of using the .atMost()
and .atLeast()
modifiers I came up with this:
ConstraintLayout {
...
Icon(
imageVector = Icons.Outlined.RequestQuote,
contentDescription = null,
modifier = Modifier.constrainAs(icon) {
top.linkTo(greeting.bottom) // some composable on top
bottom.linkTo(menuButtons.top) // some composable on bottom
start.linkTo(parent.start)
end.linkTop(parent.end)
height = Dimension.fillToConstraints.atMost(200.dp).atLeast(20.dp)
width = Dimension.fillToConstraints.atMost(200.dp).atLeast(20.dp)
}
)