Skip to content

Commit 9036af0

Browse files
committed
update adaptive layouts samples to navigable scaffolds
1 parent a7117c0 commit 9036af0

File tree

4 files changed

+261
-190
lines changed

4 files changed

+261
-190
lines changed
Lines changed: 90 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
package com.example.compose.snippets.adaptivelayouts
1818

1919
import android.os.Parcelable
20-
import androidx.activity.compose.BackHandler
2120
import androidx.compose.foundation.background
2221
import androidx.compose.foundation.clickable
2322
import androidx.compose.foundation.layout.Column
@@ -33,110 +32,158 @@ import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
3332
import androidx.compose.material3.adaptive.layout.AnimatedPane
3433
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
3534
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
35+
import androidx.compose.material3.adaptive.navigation.BackNavigationBehavior
36+
import androidx.compose.material3.adaptive.navigation.NavigableListDetailPaneScaffold
37+
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldPredictiveBackHandler
3638
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
3739
import androidx.compose.runtime.Composable
40+
import androidx.compose.runtime.rememberCoroutineScope
3841
import androidx.compose.ui.Modifier
3942
import androidx.compose.ui.graphics.Color
4043
import androidx.compose.ui.tooling.preview.Preview
4144
import androidx.compose.ui.unit.dp
4245
import androidx.compose.ui.unit.sp
46+
import kotlinx.coroutines.launch
4347
import kotlinx.parcelize.Parcelize
4448

4549
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
4650
@Composable
47-
fun SampleListDetailPaneScaffoldParts() {
48-
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part02]
49-
val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
51+
fun SampleNavigableListDetailPaneScaffoldParts() {
52+
// [START android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_part02]
53+
val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
54+
val scope = rememberCoroutineScope()
55+
// [END android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_part02]
5056

51-
BackHandler(navigator.canNavigateBack()) {
52-
navigator.navigateBack()
53-
}
54-
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part02]
55-
56-
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part03]
57-
ListDetailPaneScaffold(
58-
directive = navigator.scaffoldDirective,
59-
value = navigator.scaffoldValue,
57+
// [START android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_part03]
58+
NavigableListDetailPaneScaffold(
59+
navigator = scaffoldNavigator,
6060
// [START_EXCLUDE]
6161
listPane = {},
6262
detailPane = {},
6363
// [END_EXCLUDE]
6464
)
65-
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part03]
65+
// [END android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_part03]
6666

67-
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part04]
68-
ListDetailPaneScaffold(
69-
directive = navigator.scaffoldDirective,
70-
value = navigator.scaffoldValue,
67+
// [START android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_part04]
68+
NavigableListDetailPaneScaffold(
69+
navigator = scaffoldNavigator,
7170
listPane = {
7271
AnimatedPane {
7372
MyList(
7473
onItemClick = { item ->
7574
// Navigate to the detail pane with the passed item
76-
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
77-
}
75+
scope.launch {
76+
scaffoldNavigator
77+
.navigateTo(
78+
ListDetailPaneScaffoldRole.Detail,
79+
item
80+
)
81+
}
82+
},
7883
)
7984
}
8085
},
8186
// [START_EXCLUDE]
8287
detailPane = {},
8388
// [END_EXCLUDE]
8489
)
85-
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part04]
90+
// [END android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_part04]
8691

87-
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part05]
88-
ListDetailPaneScaffold(
89-
directive = navigator.scaffoldDirective,
90-
value = navigator.scaffoldValue,
91-
listPane =
92+
// [START android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_part05]
93+
NavigableListDetailPaneScaffold(
94+
navigator = scaffoldNavigator,
9295
// [START_EXCLUDE]
93-
{},
96+
listPane = {},
9497
// [END_EXCLUDE]
9598
detailPane = {
9699
AnimatedPane {
97-
navigator.currentDestination?.content?.let {
100+
scaffoldNavigator.currentDestination?.contentKey?.let {
98101
MyDetails(it)
99102
}
100103
}
101104
},
102105
)
103-
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part05]
106+
// [END android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_part05]
104107
}
105108

106109
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
107110
@Preview
108111
@Composable
109-
fun SampleListDetailPaneScaffoldFull() {
110-
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_full]
111-
val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
112+
fun SampleNavigableListDetailPaneScaffoldFull() {
113+
// [START android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_full]
114+
val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
115+
val scope = rememberCoroutineScope()
112116

113-
BackHandler(navigator.canNavigateBack()) {
114-
navigator.navigateBack()
115-
}
117+
NavigableListDetailPaneScaffold(
118+
navigator = scaffoldNavigator,
119+
listPane = {
120+
AnimatedPane {
121+
MyList(
122+
onItemClick = { item ->
123+
// Navigate to the detail pane with the passed item
124+
scope.launch {
125+
scaffoldNavigator.navigateTo(
126+
ListDetailPaneScaffoldRole.Detail,
127+
item
128+
)
129+
}
130+
},
131+
)
132+
}
133+
},
134+
detailPane = {
135+
AnimatedPane {
136+
// Show the detail pane content if selected item is available
137+
scaffoldNavigator.currentDestination?.contentKey?.let {
138+
MyDetails(it)
139+
}
140+
}
141+
},
142+
)
143+
// [END android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_full]
144+
}
145+
146+
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
147+
@Composable
148+
fun SampleListDetailPaneScaffoldWithPredictiveBackFull() {
149+
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_with_pb_full]
150+
val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
151+
val scope = rememberCoroutineScope()
152+
153+
ThreePaneScaffoldPredictiveBackHandler(
154+
navigator = scaffoldNavigator,
155+
backBehavior = BackNavigationBehavior.PopUntilContentChange
156+
)
116157

117158
ListDetailPaneScaffold(
118-
directive = navigator.scaffoldDirective,
119-
value = navigator.scaffoldValue,
159+
directive = scaffoldNavigator.scaffoldDirective,
160+
scaffoldState = scaffoldNavigator.scaffoldState,
120161
listPane = {
121162
AnimatedPane {
122163
MyList(
123164
onItemClick = { item ->
124165
// Navigate to the detail pane with the passed item
125-
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
166+
scope.launch {
167+
scaffoldNavigator.navigateTo(
168+
ListDetailPaneScaffoldRole.Detail,
169+
item
170+
)
171+
}
126172
},
127173
)
128174
}
129175
},
130176
detailPane = {
131177
AnimatedPane {
132178
// Show the detail pane content if selected item is available
133-
navigator.currentDestination?.content?.let {
179+
scaffoldNavigator.currentDestination?.contentKey?.let {
134180
MyDetails(it)
135181
}
136182
}
137183
},
138184
)
139-
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_full]
185+
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_with_pb_full]
186+
140187
}
141188

142189
@Composable
@@ -186,10 +233,10 @@ fun MyDetails(item: MyItem) {
186233
}
187234
}
188235

189-
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_myitem]
236+
// [START android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_myitem]
190237
@Parcelize
191238
class MyItem(val id: Int) : Parcelable
192-
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_myitem]
239+
// [END android_compose_adaptivelayouts_sample_navigable_list_detail_pane_scaffold_myitem]
193240

194241
val shortStrings = listOf(
195242
"Cupcake",
@@ -207,3 +254,4 @@ val shortStrings = listOf(
207254
"Oreo",
208255
"Pie",
209256
)
257+
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package com.example.compose.snippets.adaptivelayouts
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.layout.safeContentPadding
5+
import androidx.compose.foundation.layout.wrapContentSize
6+
import androidx.compose.material3.Button
7+
import androidx.compose.material3.Text
8+
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
9+
import androidx.compose.material3.adaptive.layout.AnimatedPane
10+
import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
11+
import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold
12+
import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole
13+
import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldPaneScope
14+
import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole
15+
import androidx.compose.material3.adaptive.navigation.BackNavigationBehavior
16+
import androidx.compose.material3.adaptive.navigation.NavigableSupportingPaneScaffold
17+
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldPredictiveBackHandler
18+
import androidx.compose.material3.adaptive.navigation.rememberSupportingPaneScaffoldNavigator
19+
import androidx.compose.runtime.Composable
20+
import androidx.compose.runtime.rememberCoroutineScope
21+
import androidx.compose.ui.Modifier
22+
import androidx.compose.ui.graphics.Color
23+
import androidx.compose.ui.tooling.preview.Preview
24+
import kotlinx.coroutines.launch
25+
26+
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
27+
@Composable
28+
fun SampleNavigableSupportingPaneScaffoldParts() {
29+
// [START android_compose_adaptivelayouts_sample_navigable_supporting_pane_scaffold_nav_and_back]
30+
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
31+
val scope = rememberCoroutineScope()
32+
33+
// [END android_compose_adaptivelayouts_sample_navigable_supporting_pane_scaffold_nav_and_back]
34+
35+
// [START android_compose_adaptivelayouts_sample_navigable_supporting_pane_scaffold_params]
36+
NavigableSupportingPaneScaffold(
37+
navigator = scaffoldNavigator,
38+
mainPane = { /*...*/ },
39+
supportingPane = { /*...*/ },
40+
)
41+
// [END android_compose_adaptivelayouts_sample_navigable_supporting_pane_scaffold_params]
42+
}
43+
44+
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
45+
@Composable
46+
@Preview
47+
fun SampleNavigableSupportingPaneScaffoldFull() {
48+
// [START android_compose_adaptivelayouts_sample_navigable_supporting_pane_scaffold_full]
49+
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
50+
val scope = rememberCoroutineScope()
51+
52+
NavigableSupportingPaneScaffold(
53+
navigator = scaffoldNavigator,
54+
mainPane = {
55+
AnimatedPane(modifier = Modifier
56+
.safeContentPadding()
57+
.background(Color.Red)
58+
) {
59+
if (scaffoldNavigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) {
60+
Button(
61+
modifier = Modifier
62+
.wrapContentSize(),
63+
onClick = {
64+
scope.launch {
65+
scaffoldNavigator.navigateTo(SupportingPaneScaffoldRole.Supporting)
66+
}
67+
}
68+
) {
69+
Text("Show supporting pane")
70+
}
71+
} else {
72+
Text("Supporting pane is shown")
73+
}
74+
}
75+
},
76+
supportingPane = {
77+
AnimatedPane(modifier = Modifier.safeContentPadding()) {
78+
Text("Supporting pane")
79+
}
80+
}
81+
)
82+
// [END android_compose_adaptivelayouts_sample_navigable_supporting_pane_scaffold_full]
83+
}
84+
85+
// [START android_compose_adaptivelayouts_sample_supporting_pane_scaffold_extracted_panes]
86+
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
87+
@Composable
88+
fun ThreePaneScaffoldPaneScope.MainPane(
89+
shouldShowSupportingPaneButton: Boolean,
90+
onNavigateToSupportingPane: () -> Unit,
91+
modifier: Modifier = Modifier,
92+
) {
93+
AnimatedPane(
94+
modifier = modifier.safeContentPadding()) {
95+
// Main pane content
96+
if (shouldShowSupportingPaneButton) {
97+
Button(onClick = onNavigateToSupportingPane) {
98+
Text("Show supporting pane")
99+
}
100+
} else {
101+
Text("Supporting pane is shown")
102+
}
103+
}
104+
}
105+
106+
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
107+
@Composable
108+
fun ThreePaneScaffoldPaneScope.SupportingPane(
109+
modifier: Modifier = Modifier,
110+
) {
111+
AnimatedPane(modifier = modifier.safeContentPadding()) {
112+
// Supporting pane content
113+
Text("This is the supporting pane")
114+
}
115+
}
116+
// [END android_compose_adaptivelayouts_sample_supporting_pane_scaffold_extracted_panes]
117+
118+
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
119+
@Composable
120+
fun SampleNavigableSupportingPaneScaffoldSimplified() {
121+
// [START android_compose_adaptivelayouts_sample_navigable_supporting_pane_scaffold_simplified]
122+
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
123+
val scope = rememberCoroutineScope()
124+
125+
NavigableSupportingPaneScaffold(
126+
navigator = scaffoldNavigator,
127+
mainPane = {
128+
MainPane(
129+
shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden,
130+
onNavigateToSupportingPane = {
131+
scope.launch {
132+
scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary)
133+
}
134+
}
135+
)
136+
},
137+
supportingPane = { SupportingPane() },
138+
)
139+
// [END android_compose_adaptivelayouts_sample_navigable_supporting_pane_scaffold_simplified]
140+
}
141+
142+
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
143+
@Composable
144+
fun SampleSupportingPaneScaffoldSimplifiedWithPredictiveBackHandler() {
145+
// [START android_compose_adaptivelayouts_sample_supporting_pane_scaffold_simplified_with_predictive_back_handler]
146+
val scaffoldNavigator = rememberSupportingPaneScaffoldNavigator()
147+
val scope = rememberCoroutineScope()
148+
149+
ThreePaneScaffoldPredictiveBackHandler(
150+
navigator = scaffoldNavigator,
151+
backBehavior = BackNavigationBehavior.PopUntilScaffoldValueChange
152+
)
153+
154+
SupportingPaneScaffold(
155+
directive = scaffoldNavigator.scaffoldDirective,
156+
scaffoldState = scaffoldNavigator.scaffoldState,
157+
mainPane = {
158+
MainPane(
159+
shouldShowSupportingPaneButton = scaffoldNavigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden,
160+
onNavigateToSupportingPane = {
161+
scope.launch {
162+
scaffoldNavigator.navigateTo(ThreePaneScaffoldRole.Secondary)
163+
}
164+
}
165+
)
166+
},
167+
supportingPane = { SupportingPane() },
168+
)
169+
// [END android_compose_adaptivelayouts_sample_supporting_pane_scaffold_simplified_with_predictive_back_handler]
170+
}

0 commit comments

Comments
 (0)