데스크톱 창 모드를 사용하면 사용자가 크기 조절이 가능한 앱 창에서 여러 앱을 동시에 실행하여 다용도 데스크톱과 유사한 환경을 경험할 수 있습니다.
그림 1은 데스크톱 창 모드가 사용 설정된 화면의 구성을 보여줍니다. 참고할 사항:
- 사용자는 여러 앱을 동시에 나란히 실행할 수 있습니다.
- 작업 표시줄은 실행 중인 앱을 표시하는 디스플레이 하단에 고정되어 있습니다. 사용자는 빠른 액세스를 위해 앱을 고정할 수 있습니다.
- 새로운 맞춤설정 가능한 헤더 표시줄은 최소화 및 최대화와 같은 컨트롤로 각 창의 상단을 장식합니다.
기본적으로 앱은 Android 태블릿에서 전체 화면으로 열립니다. 데스크톱 창 모드에서 앱을 실행하려면 화면 상단의 창 핸들을 길게 누른 후 그림 2와 같이 UI 내에서 핸들을 드래그합니다.
앱이 데스크톱 창 모드에서 열리면 다른 앱도 데스크톱 창에서 열립니다.
사용자는 핸들을 탭하거나 클릭할 때 또는 단축키 Meta 키 (Windows, Command 또는 Search) + Ctrl + 아래쪽 화살표를 사용할 때 창 핸들 아래에 표시되는 메뉴에서 데스크톱 창 모드를 호출할 수도 있습니다.
사용자는 모든 활성 창을 닫거나 데스크톱 창 상단의 창 핸들을 잡고 앱을 화면 상단으로 드래그하여 데스크톱 창 모드를 종료합니다. Meta + H 단축키를 사용해도 데스크톱 창 모드가 종료되고 앱이 다시 전체 화면으로 실행됩니다.
데스크톱 창 모드로 돌아가려면 최근 항목 화면에서 데스크톱 공간 타일을 탭하거나 클릭합니다.
크기 조절 가능성 및 호환성 모드
데스크톱 창 모드에서 방향이 잠긴 앱은 자유롭게 크기를 조절할 수 있습니다. 즉, 활동이 세로 모드로 잠겨 있더라도 사용자는 앱의 크기를 가로 모드 창으로 조절할 수 있습니다.
크기 조절이 불가능한 것으로 선언된 앱 (resizeableActivity = false)은
가로세로 비율을 동일하게 유지하면서 UI의 크기가 조정됩니다.
방향을 잠그거나 크기 조절이 불가능한 것으로 선언된 카메라 앱은 카메라 뷰파인더에 특별한 처리가 적용됩니다. 창 크기는 완전히 조절할 수 있지만 뷰파인더는 가로세로 비율을 동일하게 유지합니다. 앱이 항상 세로 또는 가로 모드로 실행된다고 가정하면 앱은 미리보기 또는 캡처된 이미지 방향 또는 가로세로 비율을 잘못 계산하여 이미지가 늘어나거나 옆으로 기울어지거나 거꾸로 표시되는 하드코딩 또는 기타 가정을 합니다.
앱이 완전히 반응형 카메라 뷰파인더를 구현할 준비가 될 때까지 특별한 처리는 잘못된 가정으로 인해 발생할 수 있는 영향을 완화하는 더 기본적인 사용자 환경을 제공합니다.
카메라 앱의 호환성 모드에 관해 자세히 알아보려면 기기 호환성 모드를 참고하세요.
맞춤설정 가능한 헤더 인셋
데스크톱 창 모드에서 실행되는 모든 앱에는 몰입형 모드에서도 헤더 표시줄이 있습니다. 이 표시줄을 맞춤설정하여 앱의 콘텐츠가 가려지지 않도록 하고 헤더 공간에 직접 맞춤 UI 요소를 그릴 수 있습니다.
구현
헤더 표시줄에 맞춤 콘텐츠를 그리려면 먼저 헤더 표시줄 배경을 투명하게 만들어야 합니다.
WindowInsetsController와 함께
APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND 플래그를 사용하여 이 작업을 실행할 수 있습니다.
window.insetsController?.setSystemBarsAppearance( WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND, WindowInsetsController.APPEARANCE_TRANSPARENT_CAPTION_BAR_BACKGROUND )
헤더 표시줄이 투명해지면 앱의 디자인에 맞게 헤더 영역의 스타일을 지정할 수 있습니다. WindowInsets.isCaptionBarVisible을 사용하여 표시줄이
있는지 감지하고 레이아웃에 적절한 높이 또는 패딩을 적용합니다.
@OptIn(ExperimentalLayoutApi::class) @Composable fun CaptionBar() { if (WindowInsets.isCaptionBarVisible) { Row( modifier = Modifier .windowInsetsTopHeight(WindowInsets.captionBar) .fillMaxWidth() .background(if (isSystemInDarkTheme()) Color.White else Color.Black), horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically ) { Text( text = "Caption Bar Title", style = MaterialTheme.typography.titleMedium, modifier = Modifier.padding(4.dp) ) } } }
setSystemBarsAppearance(appearance,mask): 시스템 표시줄의 시각적 스타일을 구성합니다. 첫 번째 매개변수는 타겟 모양 플래그를 정의하고 두 번째 매개변수는 수정되는 특정 플래그를 제어하는 마스크 역할을 합니다.windowInsetsTopHeight(): Composable의 높이를 시스템의 헤더 표시줄과 일치하도록 자동으로 설정하여 맞춤 배경이 픽셀 값을 하드코딩하지 않고도 캡션 영역을 채울 수 있도록 합니다.WindowInsets.captionBar: 데스크톱 창 모드 컨트롤 (닫기, 최대화 등)의 크기를 제공하여 데스크톱 창 모드로 전환하거나 데스크톱 창 모드를 종료할 때 UI가 자동으로 크기를 조절하거나 숨길 수 있도록 합니다.
자세한 내용은 창 인셋 정보를 참고하세요. 제목 외에도 Google Chrome과 같은 탭, 검색창 또는 프로필 아바타와 같은 다른 UI 요소를 캡션 표시줄에 표시할 수 있습니다.
사용자 인터페이스
UI가 시스템 버튼과 겹치지 않도록 Android 15는
WindowInsets#getBoundingRects() 메서드를 제공합니다. 이 메서드는 시스템 요소가 차지하는 영역을 나타내는
Rect 객체 목록을 반환합니다. 캡션 표시줄의 나머지 공간은 맞춤 콘텐츠를 안전하게 배치할 수 있는 안전지대 입니다.
APPEARANCE_LIGHT_CAPTION_BARS를 사용하여 밝은 테마와 어두운 테마의 시스템 캡션 요소 모양을 전환합니다. Compose에서
WindowInsets.Companion.captionBar()를 사용하거나 뷰에서
WindowInsets.Type.captionBar()를 사용하여 인셋에 액세스합니다.
자세한 내용은 창 인셋 정보를 참고하세요.
멀티태스킹 및 멀티 인스턴스 지원
멀티태스킹은 데스크톱 창 모드의 핵심이며 앱의 여러 인스턴스를 허용하면 사용자의 생산성을 크게 높일 수 있습니다.
Android 15부터 사용할 수 있습니다.
PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI AndroidManifest.xml에서 이 속성을 설정하면 시스템 UI가 앱을 여러 인스턴스에서 실행할 수 있는 옵션(예: '새 창' 버튼)을 제공해야 한다고 지정합니다.
<application>
<property
android:name="android.window.PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI"
android:value="true" />
</application>
참고: 데스크톱 창 모드 및 기타 멀티 윈도우 환경에서 새 작업은 새 창에서 열리므로 앱이 여러 작업을 시작할 때마다 사용자 여정을 다시 확인하세요.
드래그 동작으로 앱 인스턴스 관리
멀티 윈도우 모드에서 사용자는 앱 창에서 UI 요소 (예: 탭 또는 문서)를 드래그하여 새 앱 인스턴스를 시작할 수 있습니다. 사용자는 동일한 앱의 여러 인스턴스 간에 요소를 이동할 수도 있습니다.
드래그 앤 드롭으로 데이터 전송
사용자가 콘텐츠를 앱의 다른 인스턴스로 드래그하거나 화면의 빈 영역에 콘텐츠를 드롭하여
새 인스턴스를 만들 수 있도록 멀티 인스턴스 드래그 앤 드롭의 드래그 소스로 composable을 구성하려면
dragAndDropSource 수정자를 사용합니다. 람다에서 전송할 데이터가 포함된 ClipData와 멀티 인스턴스 동작을 구성하는 플래그를 전달하여
DragAndDropTransferData를 반환합니다.
Android 15에는 데스크톱 스타일 창 모드 및 멀티 인스턴스 상호작용을 위한 두 가지 주요 플래그가 도입되었습니다.
DRAG_FLAG_GLOBAL_SAME_APPLICATION: 드래그 작업이 창 경계를 넘을 수 있음을 나타냅니다 (동일한 애플리케이션의 여러 인스턴스). 이 플래그가 설정된 상태로startDragAndDrop()이(가) 호출되면 동일한 애플리케이션에 속한 표시되는 창만 드래그 작업에 참여하고 드래그된 콘텐츠를 수신할 수 있습니다.
Modifier.dragAndDropSource { _ -> DragAndDropTransferData( clipData = ClipData.newPlainText("label", "Your data"), flags = View.DRAG_FLAG_GLOBAL_SAME_APPLICATION ) }
DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG: 다른 창에서 드롭을 처리하지 않는 경우 사용자가 드래그된 콘텐츠를 화면의 빈 영역에 드롭하여 앱의 새 인스턴스를 시작할 수 있도록 합니다.- 이 플래그를 사용하는 경우
IntentSender를 사용하여ClipData.Item.Builder#setIntentSender()를 제공해야 합니다. 시스템은 처리되지 않은 드롭이 발생하면 이 를 사용하여 새 활동을 실행합니다.
- 이 플래그를 사용하는 경우
Modifier.dragAndDropSource { _ -> val intent = Intent.makeMainActivity(activity.componentName).apply { putExtra("EXTRA_ITEM_ID", itemId) flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK or Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT } val pendingIntent = PendingIntent.getActivity( activity, 0, intent, PendingIntent.FLAG_IMMUTABLE ) val data = ClipData( "Item $itemId", arrayOf(ClipDescription.MIMETYPE_TEXT_INTENT), ClipData.Item.Builder().setIntentSender(pendingIntent.intentSender).build() ) DragAndDropTransferData( clipData = data, flags = View.DRAG_FLAG_GLOBAL_SAME_APPLICATION or View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG, ) }
전송된 데이터 수신
다른 인스턴스의 데이터를 수락하려면 dragAndDropTarget 수정자를 사용합니다.
데이터가 다른 인스턴스 또는 앱에서 가져오는 경우 권한을 명시적으로 요청해야 합니다.
Modifier.dragAndDropTarget( shouldStartDragAndDrop = { event -> event.toAndroidDragEvent().clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN) }, target = object : DragAndDropTarget { override fun onDrop(event: DragAndDropEvent): Boolean { requestDragAndDropPermissions(activity, event.toAndroidDragEvent()) val clipData = event.toAndroidDragEvent().clipData val item = clipData?.getItemAt(0)?.text if (item != null) { // Process the dropped text item here } return item != null } } )
주요 단계:
- 필터:
shouldStartDragAndDrop을 사용하여 수신 데이터 (MIME 유형)가 지원되는지 확인합니다. - 권한:
requestDragAndDropPermissions(event)를 호출하여 데이터에 액세스합니다. - 처리:
onDrop콜백에서 데이터를 추출합니다.
추가 최적화
앱 실행을 맞춤설정하고 데스크톱 창 모드에서 전체 화면으로 앱을 전환합니다.
기본 크기 및 위치 지정
크기 조절이 가능한 앱이라도 사용자 가치를 제공하기 위해 큰 창이 필요한 것은 아닙니다. 메서드를 사용하여 활동이 실행될 때 기본
크기와 위치를 지정할 수 있습니다.ActivityOptions#setLaunchBounds()
데스크톱 공간에서 전체 화면으로 전환
앱은 Activity#requestFullScreenMode()를 호출하여 전체 화면으로 전환할 수 있습니다. 이 메서드는 데스크톱 창 모드에서 직접 앱을 전체 화면으로 표시합니다.