Skip to content

Commit 1238d26

Browse files
authored
Merge branch 'main' into stylus_snippets
2 parents 5f5654f + 9c81c6d commit 1238d26

File tree

43 files changed

+1236
-263
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+1236
-263
lines changed

bluetoothle/src/main/java/com/sample/android/bluetoothle/kotlin/DeviceScanActivity.kt

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
package com.sample.android.bluetoothle.kotlin
218

319
import android.app.ListActivity
@@ -45,4 +61,4 @@ class DeviceScanActivity : ListActivity() {
4561
}
4662
}
4763
// [END start_and_stop_scan]
48-
}
64+
}
Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,31 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
package com.sample.android.bluetoothle.kotlin
218

319
import android.bluetooth.BluetoothClass
420
import android.bluetooth.BluetoothDevice
521
import android.content.Context
622
import android.widget.ArrayAdapter
723

8-
class LeDeviceListAdapter(context: Context?, layout: Int)
9-
: ArrayAdapter<BluetoothClass.Device?>(context!!, layout) {
24+
class LeDeviceListAdapter(context: Context?, layout: Int) :
25+
ArrayAdapter<BluetoothClass.Device?>(context!!, layout) {
1026

1127
fun addDevice(device: BluetoothDevice?) {
1228
// This is where you can add devices to the adapter to
1329
// show a list of discovered devices in the UI.
1430
}
15-
}
31+
}

bluetoothle/src/main/java/com/sample/android/bluetoothle/kotlin/MainActivity.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
/*
2+
* Copyright 2025 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
117
package com.sample.android.bluetoothle.kotlin
218

319
import android.bluetooth.BluetoothAdapter

compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleListDetailPaneScaffold.kt

Lines changed: 104 additions & 32 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
@@ -30,33 +29,39 @@ import androidx.compose.material3.Card
3029
import androidx.compose.material3.ListItem
3130
import androidx.compose.material3.Text
3231
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
32+
import androidx.compose.material3.adaptive.WindowAdaptiveInfo
33+
import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo
3334
import androidx.compose.material3.adaptive.layout.AnimatedPane
3435
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffold
3536
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
37+
import androidx.compose.material3.adaptive.layout.PaneScaffoldDirective
38+
import androidx.compose.material3.adaptive.navigation.BackNavigationBehavior
39+
import androidx.compose.material3.adaptive.navigation.NavigableListDetailPaneScaffold
40+
import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldPredictiveBackHandler
3641
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
3742
import androidx.compose.runtime.Composable
43+
import androidx.compose.runtime.rememberCoroutineScope
3844
import androidx.compose.ui.Modifier
3945
import androidx.compose.ui.graphics.Color
4046
import androidx.compose.ui.tooling.preview.Preview
4147
import androidx.compose.ui.unit.dp
4248
import androidx.compose.ui.unit.sp
49+
import androidx.window.core.layout.WindowSizeClass.Companion.WIDTH_DP_EXPANDED_LOWER_BOUND
50+
import androidx.window.core.layout.WindowSizeClass.Companion.WIDTH_DP_MEDIUM_LOWER_BOUND
51+
import kotlinx.coroutines.launch
4352
import kotlinx.parcelize.Parcelize
4453

4554
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
4655
@Composable
47-
fun SampleListDetailPaneScaffoldParts() {
56+
fun SampleNavigableListDetailPaneScaffoldParts() {
4857
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part02]
49-
val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
50-
51-
BackHandler(navigator.canNavigateBack()) {
52-
navigator.navigateBack()
53-
}
58+
val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
59+
val scope = rememberCoroutineScope()
5460
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part02]
5561

5662
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part03]
57-
ListDetailPaneScaffold(
58-
directive = navigator.scaffoldDirective,
59-
value = navigator.scaffoldValue,
63+
NavigableListDetailPaneScaffold(
64+
navigator = scaffoldNavigator,
6065
// [START_EXCLUDE]
6166
listPane = {},
6267
detailPane = {},
@@ -65,16 +70,21 @@ fun SampleListDetailPaneScaffoldParts() {
6570
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part03]
6671

6772
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part04]
68-
ListDetailPaneScaffold(
69-
directive = navigator.scaffoldDirective,
70-
value = navigator.scaffoldValue,
73+
NavigableListDetailPaneScaffold(
74+
navigator = scaffoldNavigator,
7175
listPane = {
7276
AnimatedPane {
7377
MyList(
7478
onItemClick = { item ->
7579
// Navigate to the detail pane with the passed item
76-
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
77-
}
80+
scope.launch {
81+
scaffoldNavigator
82+
.navigateTo(
83+
ListDetailPaneScaffoldRole.Detail,
84+
item
85+
)
86+
}
87+
},
7888
)
7989
}
8090
},
@@ -85,16 +95,14 @@ fun SampleListDetailPaneScaffoldParts() {
8595
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part04]
8696

8797
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part05]
88-
ListDetailPaneScaffold(
89-
directive = navigator.scaffoldDirective,
90-
value = navigator.scaffoldValue,
91-
listPane =
98+
NavigableListDetailPaneScaffold(
99+
navigator = scaffoldNavigator,
92100
// [START_EXCLUDE]
93-
{},
101+
listPane = {},
94102
// [END_EXCLUDE]
95103
detailPane = {
96104
AnimatedPane {
97-
navigator.currentDestination?.content?.let {
105+
scaffoldNavigator.currentDestination?.contentKey?.let {
98106
MyDetails(it)
99107
}
100108
}
@@ -106,39 +114,103 @@ fun SampleListDetailPaneScaffoldParts() {
106114
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
107115
@Preview
108116
@Composable
109-
fun SampleListDetailPaneScaffoldFull() {
110-
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_full]
111-
val navigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
117+
fun SampleNavigableListDetailPaneScaffoldFull() {
118+
// [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_full]
119+
val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator<MyItem>()
120+
val scope = rememberCoroutineScope()
112121

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

117164
ListDetailPaneScaffold(
118-
directive = navigator.scaffoldDirective,
119-
value = navigator.scaffoldValue,
165+
directive = customScaffoldDirective,
166+
scaffoldState = scaffoldNavigator.scaffoldState,
120167
listPane = {
121168
AnimatedPane {
122169
MyList(
123170
onItemClick = { item ->
124171
// Navigate to the detail pane with the passed item
125-
navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item)
172+
scope.launch {
173+
scaffoldNavigator.navigateTo(
174+
ListDetailPaneScaffoldRole.Detail,
175+
item
176+
)
177+
}
126178
},
127179
)
128180
}
129181
},
130182
detailPane = {
131183
AnimatedPane {
132184
// Show the detail pane content if selected item is available
133-
navigator.currentDestination?.content?.let {
185+
scaffoldNavigator.currentDestination?.contentKey?.let {
134186
MyDetails(it)
135187
}
136188
}
137189
},
138190
)
139-
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_full]
140191
}
141192

193+
fun customPaneScaffoldDirective(currentWindowAdaptiveInfo: WindowAdaptiveInfo): PaneScaffoldDirective {
194+
val horizontalPartitions = when {
195+
currentWindowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(
196+
WIDTH_DP_EXPANDED_LOWER_BOUND
197+
) -> 3
198+
currentWindowAdaptiveInfo.windowSizeClass.isWidthAtLeastBreakpoint(
199+
WIDTH_DP_MEDIUM_LOWER_BOUND
200+
) -> 2
201+
else -> 1
202+
}
203+
204+
return PaneScaffoldDirective(
205+
maxHorizontalPartitions = horizontalPartitions,
206+
horizontalPartitionSpacerSize = 16.dp,
207+
maxVerticalPartitions = 1,
208+
verticalPartitionSpacerSize = 8.dp,
209+
defaultPanePreferredWidth = 320.dp,
210+
excludedBounds = emptyList()
211+
)
212+
}
213+
// [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_with_pb_full]
142214
@Composable
143215
fun MyList(
144216
onItemClick: (MyItem) -> Unit,

0 commit comments

Comments
 (0)