From 568344b3d440b13612130dc40b7425258a5e9c89 Mon Sep 17 00:00:00 2001 From: Simona <35065668+simona-anomis@users.noreply.github.com> Date: Thu, 18 Apr 2024 17:32:45 +0100 Subject: [PATCH 1/7] Update libs.versions.toml (#251) --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 173db1d6f..356661c85 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,7 +3,7 @@ accompanist = "0.32.0" androidGradlePlugin = "8.2.2" androidx-activity-compose = "1.9.0-alpha03" androidx-appcompat = "1.6.1" -androidx-compose-bom = "2024.04.00" +androidx-compose-bom = "2024.04.01" androidx-compose-ui-test = "1.7.0-alpha03" androidx-constraintlayout = "2.1.4" androidx-constraintlayout-compose = "1.0.1" From 57ebb935d5a198550a51cab34595d5fe97db7824 Mon Sep 17 00:00:00 2001 From: "Ian G. Clifton" <1033551+IanGClifton@users.noreply.github.com> Date: Wed, 1 May 2024 15:51:47 -0700 Subject: [PATCH 2/7] Updated ListDetailPaneScaffold use to alpha12 (#255) This eliminates storing state outside and directly uses the navigator as the source of truth. This also gets rid of the Modifier for AnimatedPane as it's no longer a required argument. --- build.gradle.kts | 1 + compose/snippets/build.gradle.kts | 1 + .../SampleListDetailPaneScaffold.kt | 65 ++++++------------- gradle/libs.versions.toml | 3 +- 4 files changed, 24 insertions(+), 46 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 134686249..547023ae7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.kotlin.android) apply false alias(libs.plugins.kapt) apply false alias(libs.plugins.hilt) apply false + alias(libs.plugins.kotlin.parcelize) apply false } apply("${project.rootDir}/buildscripts/toml-updater-config.gradle") diff --git a/compose/snippets/build.gradle.kts b/compose/snippets/build.gradle.kts index acfa8ddc8..48016ae8d 100644 --- a/compose/snippets/build.gradle.kts +++ b/compose/snippets/build.gradle.kts @@ -19,6 +19,7 @@ plugins { alias(libs.plugins.kotlin.android) alias(libs.plugins.kapt) alias(libs.plugins.hilt) + alias(libs.plugins.kotlin.parcelize) } android { diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleListDetailPaneScaffold.kt b/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleListDetailPaneScaffold.kt index 154ee4b36..68c14dfd8 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleListDetailPaneScaffold.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleListDetailPaneScaffold.kt @@ -16,6 +16,7 @@ package com.example.compose.snippets.adaptivelayouts +import android.os.Parcelable import androidx.activity.compose.BackHandler import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -35,33 +36,25 @@ import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.Saver -import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import kotlinx.parcelize.Parcelize @OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable fun SampleListDetailPaneScaffoldParts() { // [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part02] - val navigator = rememberListDetailPaneScaffoldNavigator() + val navigator = rememberListDetailPaneScaffoldNavigator() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() } // [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part02] - // [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part01] - var selectedItem: MyItem? by rememberSaveable(stateSaver = MyItem.Saver) { - mutableStateOf(null) - } - // [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part01] - // [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_part03] ListDetailPaneScaffold( directive = navigator.scaffoldDirective, @@ -78,13 +71,11 @@ fun SampleListDetailPaneScaffoldParts() { directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { - AnimatedPane(Modifier) { + AnimatedPane { MyList( - onItemClick = { id -> - // Set current item - selectedItem = id - // Switch focus to detail pane - navigator.navigateTo(ListDetailPaneScaffoldRole.Detail) + onItemClick = { item -> + // Navigate to the detail pane with the passed item + navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) } ) } @@ -104,9 +95,9 @@ fun SampleListDetailPaneScaffoldParts() { {}, // [END_EXCLUDE] detailPane = { - AnimatedPane(Modifier) { - selectedItem?.let { item -> - MyDetails(item) + AnimatedPane { + navigator.currentDestination?.content?.let { + MyDetails(it) } } }, @@ -119,13 +110,7 @@ fun SampleListDetailPaneScaffoldParts() { @Composable fun SampleListDetailPaneScaffoldFull() { // [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_full] - // Currently selected item - var selectedItem: MyItem? by rememberSaveable(stateSaver = MyItem.Saver) { - mutableStateOf(null) - } - - // Create the ListDetailPaneScaffoldState - val navigator = rememberListDetailPaneScaffoldNavigator() + val navigator = rememberListDetailPaneScaffoldNavigator() BackHandler(navigator.canNavigateBack()) { navigator.navigateBack() @@ -135,22 +120,20 @@ fun SampleListDetailPaneScaffoldFull() { directive = navigator.scaffoldDirective, value = navigator.scaffoldValue, listPane = { - AnimatedPane(Modifier) { + AnimatedPane { MyList( - onItemClick = { id -> - // Set current item - selectedItem = id - // Display the detail pane - navigator.navigateTo(ListDetailPaneScaffoldRole.Detail) + onItemClick = { item -> + // Navigate to the detail pane with the passed item + navigator.navigateTo(ListDetailPaneScaffoldRole.Detail, item) }, ) } }, detailPane = { - AnimatedPane(Modifier) { + AnimatedPane { // Show the detail pane content if selected item is available - selectedItem?.let { item -> - MyDetails(item) + navigator.currentDestination?.content?.let { + MyDetails(it) } } }, @@ -206,19 +189,11 @@ fun MyDetails(item: MyItem) { } // [START android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_myitem] -class MyItem(val id: Int) { - companion object { - val Saver: Saver = Saver( - { it?.id }, - ::MyItem, - ) - } -} +@Parcelize +class MyItem(val id: Int) : Parcelable // [END android_compose_adaptivelayouts_sample_list_detail_pane_scaffold_myitem] val shortStrings = listOf( - "Android", - "Petit four", "Cupcake", "Donut", "Eclair", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 356661c85..f1d252e8a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -33,7 +33,7 @@ kotlin = "1.9.20" ksp = "1.8.0-1.0.9" maps-compose = "4.3.2" material = "1.11.0" -material3-adaptive = "1.0.0-alpha08" +material3-adaptive = "1.0.0-alpha12" material3-adaptive-navigation-suite = "1.0.0-alpha05" media3 = "1.2.1" # @keep @@ -118,3 +118,4 @@ hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } version-catalog-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "version-catalog-update" } +kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } From edb4c219d30f69af2d4a40f2d33dfca00d516b0a Mon Sep 17 00:00:00 2001 From: "Ian G. Clifton" <1033551+IanGClifton@users.noreply.github.com> Date: Wed, 1 May 2024 17:21:07 -0700 Subject: [PATCH 3/7] Added NavigationSuiteScaffold snippets (#261) * Added NavigationSuiteScaffold snippets * Apply Spotless --- compose/snippets/build.gradle.kts | 1 + .../SampleNavigationSuiteScaffold.kt | 191 ++++++++++++++++++ .../src/main/res/values-es/strings.xml | 4 + .../snippets/src/main/res/values/strings.xml | 4 + gradle/libs.versions.toml | 2 +- 5 files changed, 201 insertions(+), 1 deletion(-) create mode 100644 compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleNavigationSuiteScaffold.kt diff --git a/compose/snippets/build.gradle.kts b/compose/snippets/build.gradle.kts index 48016ae8d..17b3ea12f 100644 --- a/compose/snippets/build.gradle.kts +++ b/compose/snippets/build.gradle.kts @@ -96,6 +96,7 @@ dependencies { implementation(libs.androidx.compose.material3.adaptive) implementation(libs.androidx.compose.material3.adaptive.layout) implementation(libs.androidx.compose.material3.adaptive.navigation) + implementation(libs.androidx.compose.material3.adaptive.navigation.suite) implementation(libs.androidx.compose.material) implementation(libs.androidx.compose.runtime) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleNavigationSuiteScaffold.kt b/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleNavigationSuiteScaffold.kt new file mode 100644 index 000000000..f5c461f6c --- /dev/null +++ b/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleNavigationSuiteScaffold.kt @@ -0,0 +1,191 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalMaterial3AdaptiveNavigationSuiteApi::class) + +package com.example.compose.snippets.adaptivelayouts + +import androidx.annotation.StringRes +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.AccountBox +import androidx.compose.material.icons.filled.Favorite +import androidx.compose.material.icons.filled.Home +import androidx.compose.material.icons.filled.ShoppingCart +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.NavigationBarItemDefaults +import androidx.compose.material3.Text +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo +import androidx.compose.material3.adaptive.navigationsuite.ExperimentalMaterial3AdaptiveNavigationSuiteApi +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteDefaults +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffold +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteScaffoldDefaults +import androidx.compose.material3.adaptive.navigationsuite.NavigationSuiteType +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.window.core.layout.WindowWidthSizeClass +import com.example.compose.snippets.R + +// [START android_compose_adaptivelayouts_sample_navigation_suite_scaffold_destinations] +enum class AppDestinations( + @StringRes val label: Int, + val icon: ImageVector, + @StringRes val contentDescription: Int +) { + HOME(R.string.home, Icons.Default.Home, R.string.home), + FAVORITES(R.string.favorites, Icons.Default.Favorite, R.string.favorites), + SHOPPING(R.string.shopping, Icons.Default.ShoppingCart, R.string.shopping), + PROFILE(R.string.profile, Icons.Default.AccountBox, R.string.profile), +} +// [END android_compose_adaptivelayouts_sample_navigation_suite_scaffold_destinations] + +@Composable +fun SampleNavigationSuiteScaffoldParts() { + // [START android_compose_adaptivelayouts_sample_navigation_suite_scaffold_remember] + var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) } + // [END android_compose_adaptivelayouts_sample_navigation_suite_scaffold_remember] + + // [START android_compose_adaptivelayouts_sample_navigation_suite_scaffold_items] + NavigationSuiteScaffold( + navigationSuiteItems = { + AppDestinations.entries.forEach { + item( + icon = { + Icon( + it.icon, + contentDescription = stringResource(it.contentDescription) + ) + }, + label = { Text(stringResource(it.label)) }, + selected = it == currentDestination, + onClick = { currentDestination = it } + ) + } + } + ) { + // TODO: Destination content. + } + // [END android_compose_adaptivelayouts_sample_navigation_suite_scaffold_items] + + // [START android_compose_adaptivelayouts_sample_navigation_suite_scaffold_content] + NavigationSuiteScaffold( + navigationSuiteItems = { /*...*/ } + ) { + // Destination content. + when (currentDestination) { + AppDestinations.HOME -> HomeDestination() + AppDestinations.FAVORITES -> FavoritesDestination() + AppDestinations.SHOPPING -> ShoppingDestination() + AppDestinations.PROFILE -> ProfileDestination() + } + } + // [END android_compose_adaptivelayouts_sample_navigation_suite_scaffold_content] +} + +@Composable +fun SampleNavigationSuiteScaffoldColors() { + var currentDestination by rememberSaveable { mutableStateOf(AppDestinations.HOME) } + + // [START android_compose_adaptivelayouts_sample_navigation_suite_scaffold_container_color] + NavigationSuiteScaffold( + navigationSuiteItems = { /* ... */ }, + containerColor = MaterialTheme.colorScheme.primary, + contentColor = MaterialTheme.colorScheme.onPrimary, + ) { + // Content... + } + // [END android_compose_adaptivelayouts_sample_navigation_suite_scaffold_container_color] + + // [START android_compose_adaptivelayouts_sample_navigation_suite_scaffold_suite_colors] + NavigationSuiteScaffold( + navigationSuiteItems = { /* ... */ }, + navigationSuiteColors = NavigationSuiteDefaults.colors( + navigationBarContainerColor = Color.Transparent, + ) + ) { + // Content... + } + // [END android_compose_adaptivelayouts_sample_navigation_suite_scaffold_suite_colors] + + // [START android_compose_adaptivelayouts_sample_navigation_suite_scaffold_item_colors] + val myNavigationSuiteItemColors = NavigationSuiteDefaults.itemColors( + navigationBarItemColors = NavigationBarItemDefaults.colors( + indicatorColor = MaterialTheme.colorScheme.primaryContainer, + selectedIconColor = MaterialTheme.colorScheme.onPrimaryContainer + ), + ) + + NavigationSuiteScaffold( + navigationSuiteItems = { + AppDestinations.entries.forEach { + item( + icon = { + Icon( + it.icon, + contentDescription = stringResource(it.contentDescription) + ) + }, + label = { Text(stringResource(it.label)) }, + selected = it == currentDestination, + onClick = { currentDestination = it }, + colors = myNavigationSuiteItemColors, + ) + } + }, + ) { + // Content... + } + // [END android_compose_adaptivelayouts_sample_navigation_suite_scaffold_item_colors] +} + +@Composable +fun SampleNavigationSuiteScaffoldCustomType() { + // [START android_compose_adaptivelayouts_sample_navigation_suite_scaffold_layout_type] + val adaptiveInfo = currentWindowAdaptiveInfo() + val customNavSuiteType = with(adaptiveInfo) { + if (windowSizeClass.windowWidthSizeClass == WindowWidthSizeClass.EXPANDED) { + NavigationSuiteType.NavigationDrawer + } else { + NavigationSuiteScaffoldDefaults.calculateFromAdaptiveInfo(adaptiveInfo) + } + } + + NavigationSuiteScaffold( + navigationSuiteItems = { /* ... */ }, + layoutType = customNavSuiteType, + ) { + // Content... + } + // [END android_compose_adaptivelayouts_sample_navigation_suite_scaffold_layout_type] +} + +@Composable +fun HomeDestination() {} + +@Composable +fun FavoritesDestination() {} + +@Composable +fun ShoppingDestination() {} + +@Composable +fun ProfileDestination() {} diff --git a/compose/snippets/src/main/res/values-es/strings.xml b/compose/snippets/src/main/res/values-es/strings.xml index 7507771af..cd1e2c96c 100644 --- a/compose/snippets/src/main/res/values-es/strings.xml +++ b/compose/snippets/src/main/res/values-es/strings.xml @@ -48,4 +48,8 @@ Add View entry Related Articles + Inicio + Favoritos + Compras + Perfil \ No newline at end of file diff --git a/compose/snippets/src/main/res/values/strings.xml b/compose/snippets/src/main/res/values/strings.xml index 1baab18fc..9c693cafe 100644 --- a/compose/snippets/src/main/res/values/strings.xml +++ b/compose/snippets/src/main/res/values/strings.xml @@ -48,4 +48,8 @@ Add View entry Related Articles + Home + Favorites + Shopping + Profile \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index f1d252e8a..01c5c439c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -34,7 +34,7 @@ ksp = "1.8.0-1.0.9" maps-compose = "4.3.2" material = "1.11.0" material3-adaptive = "1.0.0-alpha12" -material3-adaptive-navigation-suite = "1.0.0-alpha05" +material3-adaptive-navigation-suite = "1.0.0-alpha07" media3 = "1.2.1" # @keep minSdk = "21" From cf682eb855fef5e0117954ae8c80f1f8b622719b Mon Sep 17 00:00:00 2001 From: compose-devrel-github-bot <118755852+compose-devrel-github-bot@users.noreply.github.com> Date: Fri, 3 May 2024 09:52:00 +0100 Subject: [PATCH 4/7] =?UTF-8?q?=F0=9F=A4=96=20Update=20Dependencies=20(#26?= =?UTF-8?q?2)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 01c5c439c..2078c2124 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -4,7 +4,7 @@ androidGradlePlugin = "8.2.2" androidx-activity-compose = "1.9.0-alpha03" androidx-appcompat = "1.6.1" androidx-compose-bom = "2024.04.01" -androidx-compose-ui-test = "1.7.0-alpha03" +androidx-compose-ui-test = "1.7.0-alpha08" androidx-constraintlayout = "2.1.4" androidx-constraintlayout-compose = "1.0.1" androidx-coordinator-layout = "1.2.0" @@ -12,8 +12,8 @@ androidx-corektx = "1.9.0" androidx-emoji2-views = "1.4.0" androidx-fragment-ktx = "1.6.2" androidx-glance-appwidget = "1.0.0" -androidx-lifecycle-compose = "2.7.0" -androidx-lifecycle-runtime-compose = "2.7.0" +androidx-lifecycle-compose = "2.8.0-rc01" +androidx-lifecycle-runtime-compose = "2.8.0-rc01" androidx-navigation = "2.7.7" androidx-paging = "3.2.1" androidx-test = "1.5.0" @@ -117,5 +117,5 @@ gradle-versions = { id = "com.github.ben-manes.versions", version.ref = "gradle- hilt = { id = "com.google.dagger.hilt.android", version.ref = "hilt" } kapt = { id = "org.jetbrains.kotlin.kapt", version.ref = "kotlin" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } -version-catalog-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "version-catalog-update" } kotlin-parcelize = { id = "org.jetbrains.kotlin.plugin.parcelize", version.ref = "kotlin" } +version-catalog-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "version-catalog-update" } From ef29bb6fda5c60c3f1b6d9de4d1c500b9f49c7a0 Mon Sep 17 00:00:00 2001 From: "Ian G. Clifton" <1033551+IanGClifton@users.noreply.github.com> Date: Mon, 6 May 2024 11:30:43 -0700 Subject: [PATCH 5/7] Added snippets for SupportingPaneScaffold (#260) * Added snippets for SupportingPaneScaffold * Apply Spotless * Update compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleSupportingPaneScaffold.kt --- .../SampleSupportingPaneScaffold.kt | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleSupportingPaneScaffold.kt diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleSupportingPaneScaffold.kt b/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleSupportingPaneScaffold.kt new file mode 100644 index 000000000..ad2e0d30f --- /dev/null +++ b/compose/snippets/src/main/java/com/example/compose/snippets/adaptivelayouts/SampleSupportingPaneScaffold.kt @@ -0,0 +1,147 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@file:OptIn(ExperimentalMaterial3AdaptiveApi::class) + +package com.example.compose.snippets.adaptivelayouts + +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.safeContentPadding +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.material3.Button +import androidx.compose.material3.Text +import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi +import androidx.compose.material3.adaptive.layout.AnimatedPane +import androidx.compose.material3.adaptive.layout.PaneAdaptedValue +import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold +import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole +import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldRole +import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldScope +import androidx.compose.material3.adaptive.navigation.rememberSupportingPaneScaffoldNavigator +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier + +@Composable +fun SampleSupportingPaneScaffoldParts() { + // [START android_compose_adaptivelayouts_sample_supporting_pane_scaffold_nav_and_back] + val navigator = rememberSupportingPaneScaffoldNavigator() + + BackHandler(navigator.canNavigateBack()) { + navigator.navigateBack() + } + // [END android_compose_adaptivelayouts_sample_supporting_pane_scaffold_nav_and_back] + + // [START android_compose_adaptivelayouts_sample_supporting_pane_scaffold_params] + SupportingPaneScaffold( + directive = navigator.scaffoldDirective, + value = navigator.scaffoldValue, + mainPane = { /*...*/ }, + supportingPane = { /*...*/ }, + ) + // [END android_compose_adaptivelayouts_sample_supporting_pane_scaffold_params] +} + +@Composable +fun SampleSupportingPaneScaffoldFull() { + // [START android_compose_adaptivelayouts_sample_supporting_pane_scaffold_full] + val navigator = rememberSupportingPaneScaffoldNavigator() + + BackHandler(navigator.canNavigateBack()) { + navigator.navigateBack() + } + + SupportingPaneScaffold( + directive = navigator.scaffoldDirective, + value = navigator.scaffoldValue, + mainPane = { + AnimatedPane(modifier = Modifier.safeContentPadding()) { + // Main pane content + if (navigator.scaffoldValue[SupportingPaneScaffoldRole.Supporting] == PaneAdaptedValue.Hidden) { + Button( + modifier = Modifier.wrapContentSize(), + onClick = { + navigator.navigateTo(SupportingPaneScaffoldRole.Supporting) + } + ) { + Text("Show supporting pane") + } + } else { + Text("Supporting pane is shown") + } + } + }, + supportingPane = { + AnimatedPane(modifier = Modifier.safeContentPadding()) { + // Supporting pane content + Text("Supporting pane") + } + }, + ) + // [END android_compose_adaptivelayouts_sample_supporting_pane_scaffold_full] +} + +// [START android_compose_adaptivelayouts_sample_supporting_pane_scaffold_extracted_panes] +@Composable +fun ThreePaneScaffoldScope.MainPane( + shouldShowSupportingPaneButton: Boolean, + onNavigateToSupportingPane: () -> Unit, + modifier: Modifier = Modifier, +) { + AnimatedPane(modifier = modifier.safeContentPadding()) { + // Main pane content + if (shouldShowSupportingPaneButton) { + Button(onClick = onNavigateToSupportingPane) { + Text("Show supporting pane") + } + } else { + Text("Supporting pane is shown") + } + } +} + +@Composable +fun ThreePaneScaffoldScope.SupportingPane( + modifier: Modifier = Modifier, +) { + AnimatedPane(modifier = modifier.safeContentPadding()) { + // Supporting pane content + Text("This is the supporting pane") + } +} +// [END android_compose_adaptivelayouts_sample_supporting_pane_scaffold_extracted_panes] + +@Composable +fun SampleSupportingPaneScaffoldSimplified() { +// [START android_compose_adaptivelayouts_sample_supporting_pane_scaffold_simplified] + val navigator = rememberSupportingPaneScaffoldNavigator() + + BackHandler(navigator.canNavigateBack()) { + navigator.navigateBack() + } + + SupportingPaneScaffold( + directive = navigator.scaffoldDirective, + value = navigator.scaffoldValue, + mainPane = { + MainPane( + shouldShowSupportingPaneButton = navigator.scaffoldValue.secondary == PaneAdaptedValue.Hidden, + onNavigateToSupportingPane = { navigator.navigateTo(ThreePaneScaffoldRole.Secondary) } + ) + }, + supportingPane = { SupportingPane() }, + ) +// [END android_compose_adaptivelayouts_sample_supporting_pane_scaffold_simplified] +} From 30f5ef7366ed59a7484f3fda6c76efcc3bcd6a1f Mon Sep 17 00:00:00 2001 From: Alex Vanyo Date: Mon, 6 May 2024 15:51:35 -0700 Subject: [PATCH 6/7] Migrate to material3-adaptive WindowSizeClass method (#264) * Migrate to material3-adaptive WindowSizeClass method * Update comments to be single line --- compose/snippets/build.gradle.kts | 3 +- .../compose/snippets/glance/GlanceSnippets.kt | 8 ++-- .../layouts/AdaptiveLayoutSnippets.kt | 42 ++++++++----------- .../snippets/state/StateOverviewSnippets.kt | 2 +- gradle/libs.versions.toml | 3 +- 5 files changed, 27 insertions(+), 31 deletions(-) diff --git a/compose/snippets/build.gradle.kts b/compose/snippets/build.gradle.kts index 17b3ea12f..3930f5611 100644 --- a/compose/snippets/build.gradle.kts +++ b/compose/snippets/build.gradle.kts @@ -101,7 +101,6 @@ dependencies { implementation(libs.androidx.compose.runtime) implementation(libs.androidx.compose.runtime.livedata) - implementation(libs.androidx.compose.materialWindow) implementation(libs.androidx.compose.material.iconsExtended) implementation(libs.androidx.compose.material.ripple) implementation(libs.androidx.constraintlayout.compose) @@ -117,6 +116,8 @@ dependencies { implementation(libs.androidx.glance.appwidget) implementation(libs.androidx.glance.material3) + implementation(libs.androidx.window.core) + implementation(libs.accompanist.theme.adapter.appcompat) implementation(libs.accompanist.theme.adapter.material3) implementation(libs.accompanist.theme.adapter.material) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/glance/GlanceSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/glance/GlanceSnippets.kt index 2566a514c..aaea6a62b 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/glance/GlanceSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/glance/GlanceSnippets.kt @@ -85,8 +85,8 @@ import androidx.glance.material3.ColorProviders import androidx.glance.text.Text import androidx.work.CoroutineWorker import androidx.work.WorkerParameters +import com.example.compose.snippets.MyActivity import com.example.compose.snippets.R -import com.example.compose.snippets.layouts.MainActivity import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch @@ -167,11 +167,11 @@ private object CreateUI { Row(horizontalAlignment = Alignment.CenterHorizontally) { Button( text = "Home", - onClick = actionStartActivity() + onClick = actionStartActivity() ) Button( text = "Work", - onClick = actionStartActivity() + onClick = actionStartActivity() ) } } @@ -188,7 +188,7 @@ private object ActionLaunchActivity { // .. Button( text = "Go Home", - onClick = actionStartActivity() + onClick = actionStartActivity() ) } // [END android_compose_glance_launchactivity] diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/layouts/AdaptiveLayoutSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/layouts/AdaptiveLayoutSnippets.kt index 0db5be6b0..c66253cd6 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/layouts/AdaptiveLayoutSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/layouts/AdaptiveLayoutSnippets.kt @@ -18,22 +18,19 @@ package com.example.compose.snippets.layouts -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi -import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass -import androidx.compose.material3.windowsizeclass.WindowSizeClass -import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass +import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi +import androidx.compose.material3.adaptive.currentWindowAdaptiveInfo import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.unit.dp +import androidx.window.core.layout.WindowHeightSizeClass +import androidx.window.core.layout.WindowSizeClass /* * Copyright 2023 The Android Open Source Project @@ -51,25 +48,15 @@ import androidx.compose.ui.unit.dp * limitations under the License. */ // [START android_compose_adaptive_layouts_basic] -class MainActivity : ComponentActivity() { - @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - setContent { - val windowSizeClass = calculateWindowSizeClass(this) - MyApp(windowSizeClass) - } - } -} +@OptIn(ExperimentalMaterial3AdaptiveApi::class) @Composable -fun MyApp(windowSizeClass: WindowSizeClass) { - // Perform logic on the size class to decide whether to show - // the top app bar. - val showTopAppBar = windowSizeClass.heightSizeClass != WindowHeightSizeClass.Compact +fun MyApp( + windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().windowSizeClass +) { + // Perform logic on the size class to decide whether to show the top app bar. + val showTopAppBar = windowSizeClass.windowHeightSizeClass != WindowHeightSizeClass.COMPACT - // MyScreen knows nothing about window sizes, and performs logic - // based on a Boolean flag. + // MyScreen knows nothing about window sizes, and performs logic based on a Boolean flag. MyScreen( showTopAppBar = showTopAppBar, /* ... */ @@ -95,6 +82,13 @@ fun AdaptivePane( } // [END android_compose_layouts_adaptive_pane] +@Composable +private fun WindowSizeClassSnippet() { + // [START android_compose_windowsizeclass] + val windowSizeClass = currentWindowAdaptiveInfo().windowSizeClass + // [END android_compose_windowsizeclass] +} + @Composable fun OnePane() { // your content here diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/state/StateOverviewSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/state/StateOverviewSnippets.kt index 2ac1e62f5..503732ade 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/state/StateOverviewSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/state/StateOverviewSnippets.kt @@ -27,7 +27,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text -import androidx.compose.material3.windowsizeclass.WindowSizeClass import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue @@ -46,6 +45,7 @@ import androidx.compose.ui.res.imageResource import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.unit.dp +import androidx.window.core.layout.WindowSizeClass // [START android_compose_state_overview] @Composable diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2078c2124..62a11563d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -18,6 +18,7 @@ androidx-navigation = "2.7.7" androidx-paging = "3.2.1" androidx-test = "1.5.0" androidx-test-espresso = "3.5.1" +androidx-window = "1.3.0-beta02" androidxHiltNavigationCompose = "1.2.0" coil = "2.5.0" # @keep @@ -63,7 +64,6 @@ androidx-compose-material3-adaptive = { module = "androidx.compose.material3.ada androidx-compose-material3-adaptive-layout = { module = "androidx.compose.material3.adaptive:adaptive-layout", version.ref = "material3-adaptive" } androidx-compose-material3-adaptive-navigation = { module = "androidx.compose.material3.adaptive:adaptive-navigation", version.ref = "material3-adaptive" } androidx-compose-material3-adaptive-navigation-suite = { module = "androidx.compose.material3:material3-adaptive-navigation-suite", version.ref = "material3-adaptive-navigation-suite" } -androidx-compose-materialWindow = { module = "androidx.compose.material3:material3-window-size-class" } androidx-compose-runtime = { module = "androidx.compose.runtime:runtime" } androidx-compose-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata" } androidx-compose-ui = { module = "androidx.compose.ui:ui" } @@ -98,6 +98,7 @@ androidx-recyclerview = { module = "androidx.recyclerview:recyclerview", version androidx-test-core = { module = "androidx.test:core", version.ref = "androidx-test" } androidx-test-espresso-core = { module = "androidx.test.espresso:espresso-core", version.ref = "androidx-test-espresso" } androidx-test-runner = "androidx.test:runner:1.5.2" +androidx-window-core = { module = "androidx.window:window-core", version.ref = "androidx-window" } androidx-work-runtime-ktx = "androidx.work:work-runtime-ktx:2.9.0" coil-kt-compose = { module = "io.coil-kt:coil-compose", version.ref = "coil" } google-android-material = { module = "com.google.android.material:material", version.ref = "material" } From 2dd77e104bbf701cfa29d3ac835eae39c1fc1e7f Mon Sep 17 00:00:00 2001 From: compose-devrel-github-bot Date: Mon, 6 May 2024 22:53:28 +0000 Subject: [PATCH 7/7] Apply Spotless --- .../compose/snippets/SnippetsActivity.kt | 2 +- .../BasicSharedElementSnippets.kt | 25 ++++++++++--------- .../CustomizeSharedElementsSnippets.kt | 22 +++++++--------- .../SharedElementCommonUseCaseSnippets.kt | 1 - .../SharedElementsWithNavigationSnippets.kt | 5 +--- 5 files changed, 24 insertions(+), 31 deletions(-) diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/SnippetsActivity.kt b/compose/snippets/src/main/java/com/example/compose/snippets/SnippetsActivity.kt index bae8c6bdd..4e1e13ef8 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/SnippetsActivity.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/SnippetsActivity.kt @@ -78,7 +78,7 @@ class SnippetsActivity : ComponentActivity() { ) } Destination.ShapesExamples -> ApplyPolygonAsClipImage() - Destination.SharedElementExamples ->PlaceholderSizeAnimated_Demo() + Destination.SharedElementExamples -> PlaceholderSizeAnimated_Demo() } } } diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/BasicSharedElementSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/BasicSharedElementSnippets.kt index 989bf3668..fa7efb58b 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/BasicSharedElementSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/BasicSharedElementSnippets.kt @@ -39,7 +39,6 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -422,17 +421,19 @@ private object UniqueKeySnippet { SharedTransitionLayout { AnimatedVisibility(visible = true) { // [END_EXCLUDE] - Box(modifier = Modifier - .sharedElement( - rememberSharedContentState( - key = SnackSharedElementKey( - snackId = 1, - origin = "latest", - type = SnackSharedElementType.Image - ) - ), - animatedVisibilityScope = this@AnimatedVisibility - )) + Box( + modifier = Modifier + .sharedElement( + rememberSharedContentState( + key = SnackSharedElementKey( + snackId = 1, + origin = "latest", + type = SnackSharedElementType.Image + ) + ), + animatedVisibilityScope = this@AnimatedVisibility + ) + ) // [START_EXCLUDE] } } diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/CustomizeSharedElementsSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/CustomizeSharedElementsSnippets.kt index 51da799f7..2b6957ac0 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/CustomizeSharedElementsSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/CustomizeSharedElementsSnippets.kt @@ -30,9 +30,7 @@ import androidx.compose.animation.SharedTransitionScope import androidx.compose.animation.core.ArcMode import androidx.compose.animation.core.ExperimentalAnimationSpecApi import androidx.compose.animation.core.FastOutSlowInEasing -import androidx.compose.animation.core.Spring import androidx.compose.animation.core.keyframes -import androidx.compose.animation.core.spring import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -266,10 +264,10 @@ private fun DetailsContent( // [END android_compose_shared_element_text_bounds_transform] Text( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet lobortis velit. " + - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + - " Curabitur sagittis, lectus posuere imperdiet facilisis, nibh massa " + - "molestie est, quis dapibus orci ligula non magna. Pellentesque rhoncus " + - "hendrerit massa quis ultricies. Curabitur congue ullamcorper leo, at maximus", + "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + + " Curabitur sagittis, lectus posuere imperdiet facilisis, nibh massa " + + "molestie est, quis dapibus orci ligula non magna. Pellentesque rhoncus " + + "hendrerit massa quis ultricies. Curabitur congue ullamcorper leo, at maximus", modifier = Modifier.skipToLookaheadSize() ) } @@ -326,7 +324,7 @@ private fun SharedElement_Clipping() { rememberSharedContentState(key = "title"), animatedVisibilityScope = this@AnimatedContent, - ) + ) ) } } else { @@ -364,10 +362,10 @@ private fun SharedElement_Clipping() { ) Text( "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur sit amet lobortis velit. " + - "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + - " Curabitur sagittis, lectus posuere imperdiet facilisis, nibh massa " + - "molestie est, quis dapibus orci ligula non magna. Pellentesque rhoncus " + - "hendrerit massa quis ultricies. Curabitur congue ullamcorper leo, at maximus" + "Lorem ipsum dolor sit amet, consectetur adipiscing elit." + + " Curabitur sagittis, lectus posuere imperdiet facilisis, nibh massa " + + "molestie est, quis dapibus orci ligula non magna. Pellentesque rhoncus " + + "hendrerit massa quis ultricies. Curabitur congue ullamcorper leo, at maximus" ) } } @@ -377,7 +375,6 @@ private fun SharedElement_Clipping() { @Composable private fun JetsnackBottomBar(modifier: Modifier) { - } @Composable @@ -402,7 +399,6 @@ private fun EnterExitJetsnack() { // [END android_compose_shared_element_enter_exit] } } - } @Preview diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementCommonUseCaseSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementCommonUseCaseSnippets.kt index ce14e8399..b8dbd986a 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementCommonUseCaseSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementCommonUseCaseSnippets.kt @@ -20,7 +20,6 @@ package com.example.compose.snippets.animations.sharedelement import androidx.annotation.DrawableRes import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.ExitTransition import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.fadeIn diff --git a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementsWithNavigationSnippets.kt b/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementsWithNavigationSnippets.kt index 1551bdc8b..09c72ff4b 100644 --- a/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementsWithNavigationSnippets.kt +++ b/compose/snippets/src/main/java/com/example/compose/snippets/animations/sharedelement/SharedElementsWithNavigationSnippets.kt @@ -23,8 +23,6 @@ import androidx.compose.animation.AnimatedContentScope import androidx.compose.animation.ExperimentalSharedTransitionApi import androidx.compose.animation.SharedTransitionLayout import androidx.compose.animation.SharedTransitionScope -import androidx.compose.animation.core.TweenSpec -import androidx.compose.animation.core.tween import androidx.compose.foundation.Image import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement @@ -139,7 +137,6 @@ private fun DetailsScreen( ) } } - } @Composable @@ -194,4 +191,4 @@ data class Snack( val description: String, @DrawableRes val image: Int ) -// [END android_compose_shared_element_predictive_back] \ No newline at end of file +// [END android_compose_shared_element_predictive_back]