앱 레이아웃을 업데이트하려면 기기 기능 및 앱 상태와 같은 다양한 유형의 정보가 필요합니다. 창 너비와 높이는 가장 일반적으로 사용되는 정보입니다. 이 외에도 다음 정보를 참조할 수 있습니다.
- 창 자세
- 포인팅 기기 정밀도
- 키보드 유형
- 기기에서 카메라와 마이크를 지원하는지 여부
- 사용자와 기기 디스플레이 간의 거리
정보는 동적으로 업데이트되므로 업데이트가 발생할 때 이를 모니터링하고 재구성을 트리거해야 합니다.
mediaQuery 함수는 정보 검색의 세부정보를 추상화하고 레이아웃 업데이트를 트리거하는 조건을 정의하는 데 집중할 수 있도록 합니다.
다음 예에서는 접을 수 있는 자세가 테이블탑일 때 레이아웃을 TabletopLayout으로 전환합니다.
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
mediaQuery 함수 사용 설정
mediaQuery 함수를 사용 설정하려면
isMediaQueryIntegrationEnabled 속성을
ComposeUiFlags 객체의 true로 설정합니다.
class MyApplication : Application() { override fun onCreate() { ComposeUiFlags.isMediaQueryIntegrationEnabled = true super.onCreate() } }
매개변수로 조건 정의
람다
로 조건을 정의할 수 있습니다. 이 람다는 UiMediaScope 내에서 평가됩니다.
mediaQuery 함수는 현재 상태와 기기 기능에 따라 조건을 평가합니다.
이 함수는 불리언 값을 반환하므로 if 표현식과 같은 조건부 브랜치로 레이아웃을 결정할 수 있습니다.
표 1에서는 UiMediaScope에서 사용할 수 있는 매개변수를 설명합니다.
| 매개변수 | 값 유형 | 설명 |
|---|---|---|
windowWidth |
Dp |
현재 창 너비(dp) |
windowHeight |
Dp |
현재 창 높이(dp) |
windowPosture |
UiMediaScope.Posture |
애플리케이션 창의 현재 자세 |
pointerPrecision |
UiMediaScope.PointerPrecision |
사용 가능한 포인팅 기기의 최고 정밀도 |
keyboardKind |
UiMediaScope.KeyboardKind |
사용 가능하거나 연결된 키보드 유형 |
hasCamera |
Boolean |
기기에서 카메라가 지원되는지 여부 |
hasMicrophone |
Boolean |
기기에서 마이크가 지원되는지 여부 |
viewingDistance |
UiMediaScope.ViewingDistance |
사용자와 기기 화면 간의 일반적인 거리 |
UiMediaScope 객체는 매개변수의 값을 확인합니다.
mediaQuery 함수는 LocalUiMediaScope.current
를 사용하여 현재 기기 기능과 컨텍스트를 나타내는 UiMediaScope 객체에 액세스합니다.
이 객체는 사용자가 기기 자세를 변경하는 등 변경사항이 있을 때 동적으로 업데이트됩니다.
그런 다음 mediaQuery 함수는 업데이트된 UiMediaScope 객체로 query 람다를 평가하고 불리언 값을 반환합니다.
예를 들어 다음 스니펫은 windowPosture 매개변수 값에 따라 TabletopLayout과 FlatLayout 중에서 선택합니다.
@Composable fun VideoPlayer( // ... ) { // ... if (mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop }) { TabletopLayout() } else { FlatLayout() } // ... }
창 크기에 따라 결정
창 크기 클래스는 적응형 레이아웃을 디자인하고 개발 및 테스트할 수 있는 체계적인 표시 영역 중단점
입니다.
현재 창 크기를 나타내는 두 매개변수를 창 크기 클래스에 정의된 임곗값과 비교할 수 있습니다.
다음 예에서는 창 너비에 따라 창 수를 변경합니다.
WindowSizeClass 클래스에는 창 크기 클래스의 임곗값에 관한 상수 (그림 1)가 있습니다.
derivedMediaQuery 함수는 query 람다
를 평가하고 결과를 derivedStateOf로 래핑합니다.
windowWidth 및 windowHeight는 자주 업데이트될 수 있으므로 query 람다에서 이러한 매개변수를 참조할 때는 mediaQuery 함수 대신 derivedMediaQuery 함수를 호출하세요.
val narrowerThanMedium by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND.dp } val narrowerThanExpanded by derivedMediaQuery { windowWidth < WindowSizeClass.WIDTH_DP_EXPANDED_LOWER_BOUND.dp } when { narrowerThanMedium -> SinglePaneLayout() narrowerThanExpanded -> TwoPaneLayout() else -> ThreePaneLayout() }
창 자세에 따라 레이아웃 업데이트
windowPosture 매개변수는 현재 창 자세를 UiMediaScope.Posture 객체로 설명합니다.
매개변수
를 UiMediaScope.Posture 클래스에 정의된 값과 비교하여 현재 자세를 확인할 수 있습니다.
다음 예에서는 창 자세에 따라 레이아웃을 전환합니다.
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
사용 가능한 포인팅 기기의 정밀도 확인
정밀도가 높은 포인팅 기기를 사용하면 사용자가 UI 요소를 정확하게 가리킬 수 있습니다. 포인팅 기기의 정밀도는 기기 유형에 따라 다릅니다.
pointerPrecision 매개변수는 마우스 및 터치스크린과 같은 사용 가능한 포인팅 기기의 정밀도를 설명합니다.
UiMediaScope.PointerPrecision 클래스에는
Fine, Coarse, Blunt, None의 네 가지 값이 정의되어 있습니다.
None은 사용 가능한 포인팅 기기가 없음을 의미합니다.
정밀도는 Fine, Coarse, Blunt 순으로 가장 높음에서 가장 낮음까지 다양합니다.
여러 포인팅 기기를 사용할 수 있고 정밀도가 다른 경우 매개변수는 가장 높은 정밀도로 확인됩니다.
예를 들어 Fine 정밀도 기기와 Blunt 정밀도 기기라는 두 개의 포인팅 기기가 있는 경우 Fine은 pointerPrecision 매개변수의 값입니다.
다음 예에서는 사용자가 정밀도가 낮은 포인팅 기기를 사용하는 경우 더 큰 버튼을 보여줍니다.
if (mediaQuery { pointerPrecision == UiMediaScope.PointerPrecision.Blunt }) { LargeSizeButton() } else { NormalSizeButton() }
사용 가능한 키보드 유형 확인
keyboardKind 매개변수는 사용 가능한 키보드 유형:
Physical, Virtual, 및 None을 나타냅니다.
터치 키보드가 표시되고 하드웨어 키보드를 동시에 사용할 수 있는 경우 매개변수는 Physical로 확인됩니다.
둘 다 감지되지 않으면 None이 매개변수의 값입니다.
다음 예에서는 키보드가 감지되지 않을 때 사용자에게 키보드를 연결하라는 메시지를 보여줍니다.
if (mediaQuery { keyboardKind == UiMediaScope.KeyboardKind.None }) { SuggestKeyboardConnect() }
기기에서 카메라와 마이크를 지원하는지 확인
일부 기기에서는 카메라나 마이크를 지원하지 않습니다.
hasCamera 매개변수와 hasMicrophone 매개변수를 사용하여 기기에서 카메라와 마이크를 지원하는지 확인할 수 있습니다.
다음 예에서는 기기에서 카메라와 마이크를 지원할 때 사용할 버튼을 보여줍니다.
Row { OutlinedTextField(state = rememberTextFieldState()) // Show the MicButton when the device supports a microphone. if (mediaQuery { hasMicrophone }) { MicButton() } // Show the CameraButton when the device supports a camera. if (mediaQuery { hasCamera }) { CameraButton() } }
예상 시청 거리로 UI 조정
시청 거리는 레이아웃을 결정하는 데 도움이 되는 요소입니다.
사용자가 멀리서 앱을 사용하는 경우 텍스트와 UI 요소가 더 클 것으로 예상합니다.
viewingDistance 매개변수는 기기 유형과 일반적인 사용 컨텍스트를 기반으로 시청 거리를 추정합니다.
UiMediaScope.ViewingDistance 클래스에는
Near, Medium, Far의 세 가지 값이 정의되어 있습니다.
Near 는 화면이 가까운 범위에 있음을 의미하고 Far는 기기를 멀리서 시청함을 의미합니다.
다음 예에서는 시청 거리가 Far 또는 Medium일 때 글꼴 크기를 늘립니다.
val fontSize = when { mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Far } -> 20.sp mediaQuery { viewingDistance == UiMediaScope.ViewingDistance.Medium } -> 18.sp else -> 16.sp }
UI 구성요소 미리보기
구성 가능한 함수에서 mediaQuery 및 derivedMediaQuery 함수를 호출하여 UI 구성요소를 미리 볼 수 있습니다.
다음 스니펫은 windowPosture 매개변수 값에 따라 TabletopLayout과 FlatLayout 중에서 선택합니다.
TabletopLayout을 미리 보려면 windowPosture 매개변수가
UiMediaScope.Posture.Tabletop이어야 합니다.
when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() }
mediaQuery 및 derivedMediaQuery 함수는 UiMediaScope 객체 내에서 지정된 query 람다를 평가합니다. 이 객체는 LocalUiMediaScope.current로 제공됩니다.
다음 단계에 따라 재정의할 수 있습니다.
mediaQuery함수를 사용 설정합니다.UiMediaScope인터페이스를 구현하는 커스텀 객체를 정의합니다.- 커스텀 객체를
LocalUiMediaScope로 설정합니다.CompositionLocalProvider CompositionLocalProvider함수의 콘텐츠 람다에서 미리 볼 구성 가능한 함수를 호출합니다.
다음 예에서는 TabletopLayout을 미리 볼 수 있습니다.
@Preview @Composable fun PreviewLayoutForTabletop() { // Step 1: Enable the mediaQuery function ComposeUiFlags.isMediaQueryIntegrationEnabled = true val currentUiMediaScope = LocalUiMediaScope.current // Step 2: Define a custom object implementing the UiMediaScope interface. // The object overrides the windowPosture parameter. // The resolution of the remaining parameters is deferred to the currentUiMediaScope object. val uiMediaScope = remember(currentUiMediaScope) { object : UiMediaScope by currentUiMediaScope { override val windowPosture: UiMediaScope.Posture = UiMediaScope.Posture.Tabletop } } // Step 3: Set the object to the LocalUiMediaScope. CompositionLocalProvider(LocalUiMediaScope provides uiMediaScope) { // Step 4: Call the composable to preview. when { mediaQuery { windowPosture == UiMediaScope.Posture.Tabletop } -> TabletopLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Book } -> BookLayout() mediaQuery { windowPosture == UiMediaScope.Posture.Flat } -> FlatLayout() } } }