목록-세부정보는 하나의 창에 항목 목록을 표시하고 다른 창에 목록에서 선택한 항목의 세부정보를 표시하는 이중 창 레이아웃으로 구성된 UI 패턴입니다.
이 패턴은 대규모 컬렉션의 요소에 관한 심층적인 정보를 제공하는 애플리케이션에 특히 유용합니다. 예를 들어 이메일 목록과 각 이메일 메시지의 세부 콘텐츠가 있는 이메일 클라이언트가 있습니다.
목록-세부정보는 앱 환경설정을 카테고리 목록으로 나누고 각 카테고리의 환경설정을 세부정보 창에 표시하는 등 덜 중요한 경로에도 사용할 수 있습니다.
그림 1. 화면 크기가 충분한 경우 세부정보 창이 목록 창과 함께 표시됩니다.그림 2. 화면 크기가 제한된 경우 세부정보 창 (항목이 선택되었으므로)이 전체 공간을 차지합니다.
NavigableListDetailPaneScaffold로 목록-세부정보 패턴 구현
NavigableListDetailPaneScaffold는 Jetpack Compose에서 목록-세부정보 레이아웃을 간편하게 구현할 수 있는 컴포저블입니다. ListDetailPaneScaffold를 래핑하고 내장 탐색 및 뒤로 탐색 예측 애니메이션을 추가합니다.
Android 15 이하에서 뒤로 탐색 예측 애니메이션을 사용 설정하려면 뒤로 탐색 예측 동작을 지원하도록 선택해야 합니다. 선택하려면 AndroidManifest.xml 파일의 <application> 태그 또는 개별 <activity> 태그에 android:enableOnBackInvokedCallback="true"를 추가합니다. 자세한 내용은 뒤로 탐색 예측 동작 선택을 참고하세요.
앱이 Android 16 (API 수준 36) 이상을 타겟팅하면 기본적으로 뒤로 탐색 예측이 사용 설정됩니다.
이 탐색기는 목록, 세부정보, 추가 창 간에 이동하는 데 사용됩니다. 일반 유형을 선언하면 탐색기는 스캐폴드의 상태(즉, 표시되는 MyItem)도 추적합니다. 이 유형은 parcelable이므로 상태를 저장하고 복원하여 구성 변경을 자동으로 처리할 수 있습니다.
탐색기를 NavigableListDetailPaneScaffold 컴포저블에 전달합니다.
목록 창 구현을 NavigableListDetailPaneScaffold에 제공합니다. 탐색 중에 기본 창 애니메이션을 적용하려면 AnimatedPane을 사용하세요. 그런 다음 ThreePaneScaffoldNavigator를 사용하여 세부정보 창 ListDetailPaneScaffoldRole.Detail으로 이동하고 전달된 항목을 표시합니다.
세부정보 창 구현을 NavigableListDetailPaneScaffold에 포함합니다.
탐색이 완료되면 currentDestination에는 앱이 탐색한 창이 포함되며, 여기에는 창에 표시된 콘텐츠도 포함됩니다. contentKey 속성은 원래 호출에 지정된 것과 동일한 유형이므로 표시해야 하는 데이터에 액세스할 수 있습니다.
필요한 경우 NavigableListDetailPaneScaffold에서 defaultBackBehavior을 변경합니다. 기본적으로 NavigableListDetailPaneScaffold는 defaultBackBehavior에 PopUntilScaffoldValueChange를 사용합니다.
앱에 다른 뒤로 탐색 패턴이 필요한 경우 다른 BackNavigationBehavior 옵션을 지정하여 이 동작을 재정의할 수 있습니다.
옵션 BackNavigationBehavior개
다음 섹션에서는 한 창에 이메일 목록이 있고 다른 창에 세부정보 뷰가 있는 이메일 앱의 예를 사용합니다.
PopUntilScaffoldValueChange (기본값이며 대부분의 경우 권장됨)
이 동작은 전체 레이아웃 구조의 변경에 중점을 둡니다. 다중 창 설정에서 세부정보 창의 이메일 콘텐츠를 변경해도 기본 레이아웃 구조는 변경되지 않습니다. 따라서 현재 컨텍스트 내에서 되돌릴 레이아웃 변경사항이 없으므로 뒤로 버튼을 누르면 앱이나 현재 탐색 그래프가 종료될 수 있습니다. 단일 창 레이아웃에서는 뒤로 버튼을 누르면 세부정보 뷰 내의 콘텐츠 변경사항을 건너뛰고 목록 뷰로 돌아갑니다. 이는 명확한 레이아웃 변경을 나타내기 때문입니다.
다음 예를 고려하세요.
다중 창: 세부정보 창에서 이메일 (항목 1)을 보고 있습니다. 다른 이메일 (항목 2)을 클릭하면 세부정보 창이 업데이트되지만 목록 창과 세부정보 창은 계속 표시됩니다. 뒤로 버튼을 누르면 앱이나 현재 탐색 흐름이 종료될 수 있습니다.
단일 창: 항목 1을 본 후 항목 2를 보면 뒤로 버튼을 눌렀을 때 이메일 목록 창으로 바로 돌아갑니다.
사용자가 각 뒤로 작업으로 명확한 레이아웃 전환을 인식하도록 하려면 이를 사용하세요.
PopUntilContentChange
이 동작은 표시되는 콘텐츠에 우선순위를 부여합니다. 항목 1을 본 다음 항목 2를 보면 레이아웃에 관계없이 뒤로 버튼을 누르면 항목 1로 돌아갑니다.
다음 예를 고려하세요.
다중 창: 세부정보 창에서 항목 1을 본 다음 목록에서 항목 2를 클릭합니다. 세부정보 창이 업데이트됩니다. 뒤로를 누르면 세부정보 창이 Item 1로 복원됩니다.
단일 창: 동일한 콘텐츠 되돌리기가 발생합니다.
사용자가 뒤로 작업으로 이전에 본 콘텐츠로 돌아갈 것으로 예상하는 경우에 사용합니다.
PopUntilCurrentDestinationChange
이 동작은 현재 탐색 대상이 변경될 때까지 백 스택을 팝합니다. 이는 단일 창 레이아웃과 다중 창 레이아웃에 동일하게 적용됩니다.
다음 예를 고려하세요.
단일 또는 다중 창 레이아웃에 관계없이 뒤로 버튼을 누르면 항상 강조 표시된 탐색 요소에서 이전 대상으로 포커스가 이동합니다. 이메일 앱에서는 선택한 창의 시각적 표시가 이동합니다.
현재 탐색의 명확한 시각적 표시를 유지하는 것이 사용자 환경에 중요한 경우에 사용합니다.
PopLatest
이 옵션은 백 스택에서 가장 최근의 대상만 삭제합니다. 중간 상태를 건너뛰지 않고 뒤로 탐색하려면 이 옵션을 사용하세요.
이 단계를 구현하면 코드가 다음과 같아집니다.
valscaffoldNavigator=rememberListDetailPaneScaffoldNavigator<MyItem>()valscope=rememberCoroutineScope()NavigableListDetailPaneScaffold(navigator=scaffoldNavigator,listPane={AnimatedPane{MyList(onItemClick={item->
// Navigate to the detail pane with the passed itemscope.launch{scaffoldNavigator.navigateTo(ListDetailPaneScaffoldRole.Detail,item)}},)}},detailPane={AnimatedPane{// Show the detail pane content if selected item is availablescaffoldNavigator.currentDestination?.contentKey?.let{MyDetails(it)}}},)
이 페이지에 나와 있는 콘텐츠와 코드 샘플에는 콘텐츠 라이선스에서 설명하는 라이선스가 적용됩니다. 자바 및 OpenJDK는 Oracle 및 Oracle 계열사의 상표 또는 등록 상표입니다.
최종 업데이트: 2025-08-28(UTC)
[[["이해하기 쉬움","easyToUnderstand","thumb-up"],["문제가 해결됨","solvedMyProblem","thumb-up"],["기타","otherUp","thumb-up"]],[["필요한 정보가 없음","missingTheInformationINeed","thumb-down"],["너무 복잡함/단계 수가 너무 많음","tooComplicatedTooManySteps","thumb-down"],["오래됨","outOfDate","thumb-down"],["번역 문제","translationIssue","thumb-down"],["샘플/코드 문제","samplesCodeIssue","thumb-down"],["기타","otherDown","thumb-down"]],["최종 업데이트: 2025-08-28(UTC)"],[],[],null,["List-detail is a UI pattern that consists of a dual-pane layout where one pane\npresents a list of items and another pane displays the details of items selected\nfrom the list.\n\nThe pattern is particularly useful for applications that provide in-depth\ninformation about elements of large collections, for example, an email client\nthat has a list of emails and the detailed content of each email message.\nList-detail can also be used for less critical paths such as dividing app\npreferences into a list of categories with the preferences for each category in\nthe detail pane.\n**Figure 1.** When enough screen size is available, the detail pane is shown alongside the list pane. **Figure 2.** When screen size is limited, the detail pane (since an item has been selected) takes over the whole space.\n\nImplement the List-Detail Pattern with `NavigableListDetailPaneScaffold`\n\n`NavigableListDetailPaneScaffold` is a composable that simplifies implementing a\nlist-detail layout in Jetpack Compose. It wraps `ListDetailPaneScaffold` and\nadds built-in navigation and predictive back animations.\n\nA list-detail scaffold supports up to three panes:\n\n1. **List pane**: Displays a collection of items.\n2. **Detail pane**: Shows the details of a selected item.\n3. **Extra pane (*optional*)**: Provides additional context when needed.\n\nThe scaffold adapts based on window size:\n\n- In large windows, the list and detail panes appear side by side.\n- In small windows, only one pane is visible at a time, switching as users navigate.\n\nDeclare dependencies\n\n`NavigableListDetailPaneScaffold` is part of the [Material 3 adaptive navigation\nlibrary](/reference/kotlin/androidx/compose/material3/adaptive/layout/package-summary).\n\nAdd the following three related dependencies to the `build.gradle` file of your\napp or module: \n\nKotlin \n\n```kotlin\nimplementation(\"androidx.compose.material3.adaptive:adaptive\")\nimplementation(\"androidx.compose.material3.adaptive:adaptive-layout\")\nimplementation(\"androidx.compose.material3.adaptive:adaptive-navigation\")\n```\n\nGroovy \n\n```groovy\nimplementation 'androidx.compose.material3.adaptive:adaptive'\nimplementation 'androidx.compose.material3.adaptive:adaptive-layout'\nimplementation 'androidx.compose.material3.adaptive:adaptive-navigation'\n```\n\n- adaptive: Low-level building blocks such as [`HingeInfo`](/reference/kotlin/androidx/compose/material3/adaptive/HingeInfo) and [`Posture`](/reference/kotlin/androidx/compose/material3/adaptive/Posture)\n- adaptive-layout: Adaptive layouts such as `ListDetailPaneScaffold` and [`SupportingPaneScaffold`](/reference/kotlin/androidx/compose/material3/adaptive/layout/package-summary#SupportingPaneScaffold(androidx.compose.material3.adaptive.layout.PaneScaffoldDirective,androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue,kotlin.Function1,kotlin.Function1,androidx.compose.ui.Modifier,kotlin.Function1))\n- adaptive-navigation: Composables for navigating within and between panes, as well as adaptive layouts that support navigation by default such as `NavigableListDetailPaneScaffold` and `NavigableSupportingPaneScaffold`\n\nEnsure your project includes [compose-material3-adaptive version 1.1.0-beta1](/jetpack/androidx/releases/compose-material3-adaptive#1.1.0-beta01)\nor higher.\n\nOpt-in to the predictive back gesture\n\nTo enable predictive back animations in Android 15 or lower, you must opt-in\nto support the predictive back gesture. To opt-in, add\n`android:enableOnBackInvokedCallback=\"true\"` to the `\u003capplication\u003e` tag or\nindividual `\u003cactivity\u003e` tags within your `AndroidManifest.xml` file. For more\ninformation, see [Opt-in to the predictive back gesture](/guide/navigation/custom-back/predictive-back-gesture#opt-predictive).\n\nOnce your app targets Android 16 (API level 36) or higher, predictive back is\nenabled by default.\n\nBasic usage\n\nImplement `NavigableListDetailPaneScaffold` as follows:\n\n1. Use a class that represents the selected content. Use a [`Parcelable`](/reference/android/os/Parcelable) class to support saving and restoring the selected list item. Use the [kotlin-parcelize plugin](/kotlin/parcelize) to generate the code for you.\n2. Create a `ThreePaneScaffoldNavigator` with `rememberListDetailPaneScaffoldNavigator`.\n\nThis navigator is used to move between the list, detail, and extra panes. By\ndeclaring a generic type, the navigator also tracks the state of the scaffold\n(that is, which `MyItem` is being displayed). Since this type is parcelable, the\nstate can be saved and restored by the navigator to automatically handle\nconfiguration changes.\n\n1. Pass the navigator to the `NavigableListDetailPaneScaffold` composable.\n\n2. Supply your list pane implementation to the\n `NavigableListDetailPaneScaffold`. Use [`AnimatedPane`](/reference/kotlin/androidx/compose/material3/adaptive/layout/ThreePaneScaffoldScope#(androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope).AnimatedPane(androidx.compose.ui.Modifier,kotlin.Function1)) to apply the\n default pane animations during navigation. Then use `ThreePaneScaffoldNavigator`\n to navigate to the detail pane, `ListDetailPaneScaffoldRole.Detail`, and display\n the passed item.\n\n3. Include your detail pane implementation in `NavigableListDetailPaneScaffold`.\n\nWhen navigation is complete, `currentDestination` contains the pane your app\nhas navigated to, including the content displayed in the pane. The `contentKey`\nproperty is the same type specified in the original call so you can access\nany data that you need to display.\n\n1. Optionally, change the `defaultBackBehavior` in `NavigableListDetailPaneScaffold`. By default, `NavigableListDetailPaneScaffold` uses `PopUntilScaffoldValueChange` for `defaultBackBehavior`.\n\nIf your app requires a different back navigation pattern, you can override this\nbehavior by specifying another `BackNavigationBehavior` option.\n\n`BackNavigationBehavior` options\n\nThe following section uses the example of an email app with a list of emails in\none pane and a detailed view in the other.\n\n`PopUntilScaffoldValueChange` (Default and recommended in most cases)\n\nThis behavior focuses on changes to the overall layout structure. In a\nmulti-pane setup, changing the email content in the detailed pane doesn't alter\nthe underlying layout structure. Therefore, the back button might exit the app\nor the current navigation graph because there's no layout change to revert to\nwithin the current context. In a single-pane layout, pressing back will skip\nthrough content changes within the detail view and return to the list view, as\nthis represents a clear layout change.\n\nConsider the following examples:\n\n- **Multi-Pane:** You're viewing an email (Item 1) in the detail pane. Clicking on another email (Item 2) updates the detail pane, but the list and detail panes remain visible. Pressing back might exit the app or the current navigation flow.\n- **Single-Pane:** You view Item 1, then Item 2, pressing back will return you directly to the email list pane.\n\nUse this when you want users to perceive distinct layout transitions with each\nback action.\n\n`PopUntilContentChange`\n\nThis behavior prioritizes the content displayed. If you view Item 1 and then\nItem 2, pressing back will revert to Item 1, regardless of the layout.\n\nConsider the following examples:\n\n- **Multi-Pane:** You view Item 1 in the detail pane, then click Item 2 in the list. The detail pane updates. Pressing back will restore the detail pane to Item 1.\n- **Single-Pane:** The same content reversion occurs.\n\nUse this when your user expects to return to the previously viewed content with\nthe back action.\n\n`PopUntilCurrentDestinationChange`\n\nThis behavior pops the back stack until the *current navigation destination*\nchanges. This applies equally to single and multi-pane layouts.\n\nConsider the following examples:\n\nRegardless of whether you're in a single or multi-pane layout, pressing back\nwill always move the focus from the highlighted navigation element to the\nprevious destination. In our email app, this means the visual indication of\nthe selected pane will shift.\n\nUse this when maintaining a clear visual indication of the current navigation\nis crucial for the user experience.\n\n`PopLatest`\n\nThis option removes only the most recent destination from the backstack. Use\nthis option for back navigation without skipping intermediate states.\n| **Note:** Multi-pane layouts may create navigation backstacks that are not possible in single-pane layouts, such as navigating directly from one detail item to another. If the device size changes mid-navigation, this behavior may produce unintuitive results.\n\nAfter you implement these steps, your code should look similar to the following:\n\n\n```kotlin\nval scaffoldNavigator = rememberListDetailPaneScaffoldNavigator\u003cMyItem\u003e()\nval scope = rememberCoroutineScope()\n\nNavigableListDetailPaneScaffold(\n navigator = scaffoldNavigator,\n listPane = {\n AnimatedPane {\n MyList(\n onItemClick = { item -\u003e\n // Navigate to the detail pane with the passed item\n scope.launch {\n scaffoldNavigator.navigateTo(\n ListDetailPaneScaffoldRole.Detail,\n item\n )\n }\n },\n )\n }\n },\n detailPane = {\n AnimatedPane {\n // Show the detail pane content if selected item is available\n scaffoldNavigator.currentDestination?.contentKey?.let {\n MyDetails(it)\n }\n }\n },\n)https://github.com/android/snippets/blob/f95ab59fad80aeaf5d6a90bab8a01a126f20f44e/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleListDetailPaneScaffold.kt#L119-L147\n```\n\n\u003cbr /\u003e"]]