시배's Android
Compose Docs | Instrinsic measurements 본문
Compose 레이아웃의 내장 기능 측정 | Jetpack Compose | Android Developers
Compose 레이아웃의 내장 기능 측정 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Compose 규칙 중 하나는 하위 요소를 한 번만 측정해야 한다는 것입니다. 하
developer.android.com
Compose의 규칙 중 하나는 자녀를 한 번만 측정해야 하며, 자녀를 두 번 측정하면 런타임 예외가 발생한다는 것입니다. 그러나 자녀를 측정하기 전에 자녀에 대한 정보가 필요한 경우가 있습니다.
Intrinsics를 사용하면 실제로 측정하기 전에 자식에 대해 쿼리할 수 있습니다.
컴포저블에 대해, 그 컴포저블의 intrinsicWidth 또는 intrinsicHeight를 요청할 수 있습니다:
(최소|최대)IntrinsicWidth: 이 높이가 주어졌을 때 콘텐츠를 제대로 칠할 수 있는 최소/최대 너비는 얼마인가?
(최소|최대)IntrinsicHeight: 이 너비가 주어졌을 때 콘텐츠를 제대로 칠할 수 있는 최소/최대 높이는 얼마인가요?
예를 들어 너비가 무한대인 텍스트의 최소 내재 높이를 물어보면 텍스트가 한 줄로 그려진 것처럼 텍스트의 높이를 반환합니다.
Instrinsics in action
이렇게 디바이더로 구분된 두 개의 텍스트를 화면에 표시하는 컴포저블을 만들고 싶다고 가정해 보겠습니다:
어떻게 할 수 있을까요? 내부에 두 개의 텍스트가 있는 행을 최대한 확장하고 가운데에 디바이더를 배치하면 됩니다. 디바이더는 가장 긴 텍스트만큼 길고 얇아야 합니다(너비 = 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
)
Divider(
color = Color.Black,
modifier = Modifier.fillMaxHeight().width(1.dp)
)
Text(
modifier = Modifier
.weight(1f)
.padding(end = 4.dp)
.wrapContentWidth(Alignment.End),
text = text2
)
}
}
미리 보기를 보면 디바이더가 전체 화면으로 확장되는 것을 볼 수 있는데, 이는 우리가 원하는 것이 아닙니다:
이는 행이 각 자식을 개별적으로 측정하고 텍스트의 높이를 사용하여 디바이더를 제약할 수 없기 때문에 발생합니다. 우리는 디바이더가 주어진 높이로 사용 가능한 공간을 채우기를 원합니다. 이를 위해 높이(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
)
Divider(
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 컴포저블의 최소 고유 높이는 그 자손의 최대 minIntrinsicHeight가 됩니다. 제약 조건이 주어지지 않으면 공간을 차지하지 않으므로 Divider 엘리먼트의 minIntrinsicHeight는 0이 되고, Text 엘리먼트의 minIntrinsicHeight는 특정 너비가 지정된 텍스트의 높이가 됩니다. 따라서 행 요소의 높이 제약 조건은 텍스트의 최대 minIntrinsicHeight가 됩니다. 그러면 디바이더는 행에 지정된 높이 제약 조건까지 높이를 확장합니다.
Intrinsics in your custom layouts
사용자 정의 레이아웃 또는 레이아웃 수정자를 만들 때 근사치를 기반으로 내재적 측정값이 자동으로 계산됩니다. 따라서 모든 레이아웃에서 계산이 정확하지 않을 수 있습니다. 이러한 API는 이러한 기본값을 재정의할 수 있는 옵션을 제공합니다.
사용자 지정 레이아웃의 내재적 측정값을 지정하려면 레이아웃을 만들 때 측정정책 인터페이스의 최소 내재적 너비, 최소 내재적 높이, 최대 내재적 너비 및 최대 내재적 높이를 재정의합니다.
@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.
}
)
}
사용자 정의 레이아웃 수정자를 만들 때 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.
}
'Android > Compose Docs' 카테고리의 다른 글
Compose Docs | Custom Design Systems (0) | 2023.09.16 |
---|---|
Compose Docs | ConstraintLayout (0) | 2023.09.06 |
Compose Docs | Alignment lines (0) | 2023.09.03 |
Compose Docs | Build adaptive layouts (0) | 2023.08.28 |
Compose Docs | Custom layouts (0) | 2023.08.26 |