Compose 규칙 중 하나는 하위 요소를 한 번만 측정해야 한다는 것입니다. 하위 요소를 두 번 측정하면 런타임 예외가 발생합니다. 하지만 하위 요소를 측정하기 전에 하위 요소에 관한 정보가 필요한 경우도 있습니다.
내장 기능을 사용하면 하위 요소가 실제로 측정되기 전에 하위 요소를 쿼리할 수 있습니다.
컴포저블에 IntrinsicSize.Min
또는 IntrinsicSize.Max
를 요청할 수 있습니다.
Modifier.width(IntrinsicSize.Min)
- 콘텐츠를 적절하게 표시하는 데 필요한 최소 너비는 무엇인가요?Modifier.width(IntrinsicSize.Max)
- 콘텐츠를 적절하게 표시하는 데 필요한 최대 너비는 무엇인가요?Modifier.height(IntrinsicSize.Min)
- 콘텐츠를 적절하게 표시하는 데 필요한 최소 높이는 무엇인가요?Modifier.height(IntrinsicSize.Max)
- 콘텐츠를 적절하게 표시하는 데 필요한 최대 높이는 무엇인가요?
예를 들어 맞춤 레이아웃에서 width
제약 조건이 무한대인 Text
의 minIntrinsicHeight
를 요청하면 텍스트가 한 줄에 그려진 Text
의 height
가 반환됩니다.
내장 기능 실제 사례
구분선으로 구분된 두 텍스트를 화면에 표시하는 컴포저블을 만들 수 있습니다.
이렇게 하려면 사용 가능한 공간을 채우는 두 개의 Text
컴포저블과 가운데에 있는 Divider
를 사용하여 Row
를 사용합니다. Divider
는 가장 높은 Text
만큼 높아야 하고 가늘어야 합니다 (width = 1.dp
).
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } }
Divider
가 전체 화면으로 확장되는데 이는 원하는 동작이 아닙니다.
Row
가 각 하위 요소를 개별적으로 측정하며 Text
의 높이를 사용하여 Divider
를 제약할 수 없기 때문에 이러한 결과가 발생합니다.
Divider
가 가용 공간을 지정된 높이로 채우도록 하려면 height(IntrinsicSize.Min)
수정자를 사용하세요.
height(IntrinsicSize.Min)
는 하위 요소의 크기를 고유한 최소 높이로 지정합니다. 이 수정자는 반복적이므로 Row
및 그 하위 요소의 minIntrinsicHeight
를 쿼리합니다.
이 수정자를 코드에 적용하면 예상대로 작동합니다.
@Composable fun TwoTexts(modifier: Modifier = Modifier, text1: String, text2: String) { Row(modifier = modifier.height(IntrinsicSize.Min)) { Text( modifier = Modifier .weight(1f) .padding(start = 4.dp) .wrapContentWidth(Alignment.Start), text = text1 ) VerticalDivider( color = Color.Black, modifier = Modifier.fillMaxHeight().width(1.dp) ) Text( modifier = Modifier .weight(1f) .padding(end = 4.dp) .wrapContentWidth(Alignment.End), text = text2 ) } } // @Preview @Composable fun TwoTextsPreview() { MaterialTheme { Surface { TwoTexts(text1 = "Hi", text2 = "there") } } }
미리보기는 다음과 같습니다.
Row
의 높이는 다음과 같이 결정됩니다.
Row
컴포저블의minIntrinsicHeight
는 하위 요소의 최대minIntrinsicHeight
입니다.Divider
요소의minIntrinsicHeight
는 제약 조건이 주어지지 않으면 공간을 차지하지 않으므로 0입니다.Text
minIntrinsicHeight
은 특정width
의 텍스트입니다.- 따라서
Row
요소의height
제약 조건은Text
의 최대minIntrinsicHeight
가 됩니다. - 그런 다음
Divider
가height
를Row
가 지정한height
제약 조건으로 확장합니다.
맞춤 레이아웃의 내장 기능
맞춤 Layout
또는 layout
수정자를 만들 때 내장 기능 측정은 근사값에 따라 자동으로 계산됩니다. 따라서 일부 레이아웃의 계산은 정확하지 않을 수 있습니다. 이러한 API는 이와 같은 기본값을 재정의하는 옵션을 제공합니다.
맞춤 Layout
의 내장 기능 측정을 지정하려면 만들 때 MeasurePolicy
인터페이스의 minIntrinsicWidth
, minIntrinsicHeight
, maxIntrinsicWidth
, maxIntrinsicHeight
를 재정의하세요.
@Composable fun MyCustomComposable( modifier: Modifier = Modifier, content: @Composable () -> Unit ) { Layout( content = content, modifier = modifier, measurePolicy = object : MeasurePolicy { override fun MeasureScope.measure( measurables: List<Measurable>, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurables: List<IntrinsicMeasurable>, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. } ) }
맞춤 layout
수정자를 만들 때 LayoutModifier
인터페이스에서 관련 메서드를 재정의합니다.
fun Modifier.myCustomModifier(/* ... */) = this then object : LayoutModifier { override fun MeasureScope.measure( measurable: Measurable, constraints: Constraints ): MeasureResult { // Measure and layout here // ... } override fun IntrinsicMeasureScope.minIntrinsicWidth( measurable: IntrinsicMeasurable, height: Int ): Int { // Logic here // ... } // Other intrinsics related methods have a default value, // you can override only the methods that you need. }
추천 서비스
- 참고: JavaScript가 사용 중지되어 있으면 링크 텍스트가 표시됩니다.
- 맞춤 레이아웃 {:#custom-layouts}
- Jetpack Compose의 정렬 선
- Jetpack Compose 단계