Реагирующий размер Jetpack Compose в ConstraintLayout — Dimension.fillToConstraints перезаписывает модификаторы .sizeIn, .widthIn, .heightIn

Я пытаюсь иметь компонуемую шкалу внутриConstrainLayoutпока не будет достигнут указанный максимальный размер (обычно путем установки или модификатора) или не будут достигнуты границы ограничений.

Использование only или приведет к отображению компонуемого всегда в минимальном размере.

Итак, мы указываем.fillMaxSizeна компонуемый, чтобы занимать максимальное количество места (до указанного maxSize). Все идет нормально..

Но теперь, когда ConstraintLayout становится меньше, например, из-за меньшего экрана и, следовательно, границы компонуемого превышают ограничения, компонуемый не уменьшается.

Это кажется понятным, потому что мы не указали, что размер компонуемого должен ориентироваться на границы указанных ограничений. Поэтому мы указываем и используем только пространство, вытекающее из заданных ограничений.

И тут возникает проблема.height = Dimensions.fillToConstraintsиwidth = Dimensions.fillToConstraintsкажется, перезаписывают.sizeIn,.widthInили.heightInМодификатор, потому что теперь размер компонуемого всегда настолько велик, насколько он может быть внутри заданных ограничений, не обращая внимания наmaxWidthилиmaxHeightуказано ранее.

Обходной путь — поместить этот компонуемый объект в другой, например, в блок, и настроить модификатор следующим образом:

      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)
            )
        }
      ...
}

Это дало бы нам желаемое поведение. Но, на мой взгляд, дополнительно указанное поле представляет собой ненужные накладные расходы. Итак, мой вопрос:

Есть ли способ получить это поведение без использования вторичного компонуемого только с использованием определенной конфигурации модификатора?

2 ответа

Основываясь на ответе @hoford, который подал мне идею использования.atMost()и.atLeast()модификаторы, которые я придумал:

      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)
            }
    )

Это можно сделать непосредственно в ограничениях ограничения. Я думаю, что вы ищете что-то вроде

      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.preferredWrapContent.atMost(200.dp).atLeast(20.dp)
                width = Dimension.preferredWrapContent.atMost(200.dp).atLeast(20.dp)
            }
    )