From d168ab767cb038caee9847e83ed213b6c6aab1db Mon Sep 17 00:00:00 2001 From: android-devrel-github-bot Date: Tue, 15 Sep 2026 08:50:46 +0000 Subject: [PATCH] Updates skills (2026-09-15 08:50) --- identity/restore-credentials/SKILL.md | 16 +- jetpack-compose/theming/styles/SKILL.md | 2 +- .../develop/ui/compose/styles/fundamentals.md | 42 +- navigation/navigation-3/SKILL.md | 4 +- .../guide/navigation/navigation-3/index.md | 11 +- .../navigation-3/migration-guide.md | 95 ++++- .../navigation-3/recipes/conditional.md | 12 +- .../recipes/deeplinks-uriarguments.md | 390 ------------------ wear/wear-compose-m3/SKILL.md | 42 +- .../foundation/SwipeToDismissBoxSample.kt.md | 3 +- .../SwipeToDismissBoxSample.kt.md.txt | 3 +- .../material3/CheckboxButtonSample.kt.md | 4 +- .../material3/CheckboxButtonSample.kt.md.txt | 4 +- .../material3/PlaceholderSample.kt.md | 4 +- .../material3/PlaceholderSample.kt.md.txt | 4 +- .../material3/RadioButtonSample.kt.md | 8 +- .../material3/RadioButtonSample.kt.md.txt | 8 +- .../SurfaceTransformationSample.kt.md | 5 +- .../SurfaceTransformationSample.kt.md.txt | 5 +- .../material3/SwipeToDismissBoxSample.kt.md | 3 +- .../SwipeToDismissBoxSample.kt.md.txt | 3 +- .../material3/SwipeToRevealSample.kt.md | 9 +- .../material3/SwipeToRevealSample.kt.md.txt | 9 +- .../material3/SwitchButtonSample.kt.md | 4 +- .../material3/SwitchButtonSample.kt.md.txt | 4 +- .../SwipeDismissableSceneStrategySample.kt.md | 205 +++++++++ ...peDismissableSceneStrategySample.kt.md.txt | 205 +++++++++ .../SKILL.md | 2 +- .../references/projectedcontext-source.md | 104 +++-- .../references/stack-source.md | 11 +- .../references/surface-source.md | 20 +- 31 files changed, 684 insertions(+), 557 deletions(-) delete mode 100644 navigation/navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-uriarguments.md create mode 100644 wear/wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md create mode 100644 wear/wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt diff --git a/identity/restore-credentials/SKILL.md b/identity/restore-credentials/SKILL.md index 35dbd2c..cc9078c 100644 --- a/identity/restore-credentials/SKILL.md +++ b/identity/restore-credentials/SKILL.md @@ -9,7 +9,7 @@ description: Provides knowledge and workflows to implement Android's Restore Cre license: Complete terms in LICENSE.txt metadata: author: Google LLC - last-updated: '2026-09-01' + last-updated: '2026-09-14' keywords: - Credential Manager - Restore Credentials @@ -205,7 +205,7 @@ restore key by wrapping these options in a - `false`: This value saves the key locally and not in the cloud. The key is not available on the new device if the user chooses to restore from the cloud. > [!CAUTION] - > **Caution:** It's recommended to set `isCloudBackupEnabled` to `true`. If cloud backup is disabled and the user restores from a cloud backup, the call to retrieve the restore key fails. Users who restore your app with a cloud backup don't receive the restore key and are not automatically signed in. + > **Caution:** It's recommended to set `isCloudBackupEnabled` to `true`. If cloud backup is disabled and the user restores from a cloud backup, the call to retrieve the restore key fails. Users who restore your app with a cloud backup don't receive the restore key and aren't automatically signed in. ### Handle the credential creation response @@ -248,8 +248,8 @@ It's recommended to fetch the restore key in both of the following scenarios: - On the first launch of the app on the device. Credential restoration in this scenario is independent of restoration of the app data. - If app data backup and restore is enabled, get the restore key immediately after the app data is restored. Use [`BackupAgent`](https://developer.android.com/reference/android/app/backup/BackupAgent) to configure your app's backup and ensure you complete the `getCredential` functionality within the [`onRestoreFinished`](https://developer.android.com/reference/android/app/backup/BackupAgent#onRestoreFinished()) callback. Don't use the `onRestore` method, as it is only called for key-value backups, whereas `onRestoreFinished` is reliably called for any kind of backup restore. This avoids potential delays when users open their new device for the first time and lets users interact with the app without waiting for them to open your app. For example, this lets your app send the user notifications before they open the app for the first time on the new device, which is particularly relevant for messaging or communications apps. -If you newly create a `BackupAgent` and previously had backup enabled with -`allowBackup="true"`, set the boolean value `android:fullBackupOnly="true"`in +If you create a new `BackupAgent` and previously had backup enabled with +`allowBackup="true"`, set the boolean value `android:fullBackupOnly="true"` in your app's manifest. This ensures that your app's backup and restore behavior is maintained. @@ -287,10 +287,13 @@ the server-side implementation for passkeys, see [Sign in with a passkey](refere Credential Manager is stateless and unaware of user activity, so it doesn't automatically delete restore keys after use. To delete a restore key, call the -`clearCredentialState()` method. For security, delete the key whenever a user +`clearCredentialState` method. For security, delete the key whenever a user signs out. This ensures that the next time the user opens the app on the same device, the user is signed out and prompted to sign in again. +> [!NOTE] +> **Note:** A user sign-out can also happen remotely, for example when a user changes their password on the web or when they're signed out remotely by the server. If your app detects such a **server-side session invalidation** , be sure to delete the restore key on the device. (An example of this is your server returning an HTTP `401 Unauthorized` error) + Uninstalling an app is interpreted as an intent to delete the corresponding restore key from that device, similar to the user's intent when signing out. @@ -331,6 +334,9 @@ developer as a reminder after the client-side implementation is complete.** 4. **Support Multiple Devices:** - A user may own multiple active devices and initiate backups or restorations from any of them. - **Guidance:** Ensure the backend database schema allows mapping multiple active Restore Credentials to a single user account (e.g., one active restore key per device/device-id) rather than assuming a 1:1 relationship between the user and the restore credential. +5. **Server-side session invalidation:** + - A user's session might be revoked remotely. This could be triggered by user actions such as when a user resets their password on the web or server actions that can cause the API to return HTTP `401 Unauthorized` indicating session expiry. + - **Guidance:** If this applies, make sure to clear the user's restore credentials on the phone when it happens. ## References diff --git a/jetpack-compose/theming/styles/SKILL.md b/jetpack-compose/theming/styles/SKILL.md index cc6cc95..2af7e49 100644 --- a/jetpack-compose/theming/styles/SKILL.md +++ b/jetpack-compose/theming/styles/SKILL.md @@ -8,7 +8,7 @@ description: Use this skill to integrate the Jetpack Compose Styles API into an license: Complete terms in LICENSE.txt metadata: author: Google LLC - last-updated: '2026-09-03' + last-updated: '2026-09-08' keywords: - Jetpack Compose - Styles diff --git a/jetpack-compose/theming/styles/references/android/develop/ui/compose/styles/fundamentals.md b/jetpack-compose/theming/styles/references/android/develop/ui/compose/styles/fundamentals.md index 73d4a9e..ab0d26d 100644 --- a/jetpack-compose/theming/styles/references/android/develop/ui/compose/styles/fundamentals.md +++ b/jetpack-compose/theming/styles/references/android/develop/ui/compose/styles/fundamentals.md @@ -42,7 +42,8 @@ BaseButton( onClick = { }, style = { } ) { - BaseText("Click mnippets.kt + BaseText("Click me") +} ```
@@ -56,7 +57,8 @@ BaseButton( onClick = { }, style = { background(Color.Blue) } ) { - BaseText("Click mnippets.kt + BaseText("Click me") +} ```
@@ -75,7 +77,8 @@ own custom components. Row( modifier = Modifier.styleable { } ) { - BaseText("Contennippets.kt + BaseText("Content") +} ```
@@ -90,7 +93,8 @@ Row( background(Color.Blue) } ) { - BaseText("Contennippets.kt + BaseText("Content") +} ```
@@ -141,8 +145,8 @@ val styleState = remember { MutableStyleState(null) } Column( Modifier.styleable(styleState, style) ) { - BaseText("Col) -}StylesSnippets.kt + BaseText("Column content") +} ```
@@ -168,8 +172,10 @@ Column( } val rowStyleState = remember { MutableStyleState(null) } Row( - Modifier.styleable(rowStyleState, stText("Row") -}StylesSnippets.kt + Modifier.styleable(rowStyleState, style) +) { + BaseText("Row") +} ```
@@ -188,7 +194,8 @@ BaseButton( contentPaddingStart(16.dp) } ) { - BaseText("Buttonippets.kt + BaseText("Button") +} ```
@@ -218,7 +225,8 @@ BaseButton( // } ) { - BaseText("Click menippets.kt + BaseText("Click me!") +} ```
@@ -242,7 +250,8 @@ BaseButton( }, ) { - BaseText("Click menippets.kt + BaseText("Click me!") +} ```
@@ -274,7 +283,8 @@ BaseButton( }, ) { - BaseText("Click menippets.kt + BaseText("Click me!") +} ```
@@ -324,8 +334,8 @@ Column( ) { BaseText("Children inherit", style = { width(60.dp) }) BaseText("certain properties") - BaseText(&quents") -}StylesSnippets.kt + BaseText("from their parents") +} ```
@@ -355,8 +365,8 @@ Column( contentBrush(Brush.linearGradient(listOf(Color.Red, Color.Blue))) }) BaseText("override properties") - BaseText("ents") -}StylesSnippets.kt + BaseText("set by their parents") +} ```
diff --git a/navigation/navigation-3/SKILL.md b/navigation/navigation-3/SKILL.md index e40f8d0..41436e5 100644 --- a/navigation/navigation-3/SKILL.md +++ b/navigation/navigation-3/SKILL.md @@ -8,7 +8,7 @@ description: Learn how to install and migrate to Jetpack Navigation 3, and how t license: Complete terms in LICENSE.txt metadata: author: Google LLC - last-updated: '2026-09-01' + last-updated: '2026-09-10' keywords: - recipe - Android @@ -64,7 +64,7 @@ Code examples showcasing common patterns. ### Deep links - *[Static URI](references/android/guide/navigation/navigation-3/recipes/deeplinks-staticuri.md)*: Shows how to handle simple static URI deep links. -- *[URI with Arguments](references/android/guide/navigation/navigation-3/recipes/deeplinks-uriarguments.md)*: Shows how to parse path and query arguments from a deep link. +- *[URI with Arguments](https://developer.android.com/guide/navigation/navigation-3/recipes/deeplinks-uriarguments)*: Shows how to parse path and query arguments from a deep link. - *[Synthetic BackStack](references/android/guide/navigation/navigation-3/recipes/deeplinks-syntheticbackstack.md)*: Shows how to handle deep links with a synthetic back stack. - *[Custom Matcher](references/android/guide/navigation/navigation-3/recipes/deeplinks-custommatcher.md)*: Shows how to implement custom deep link matching logic. diff --git a/navigation/navigation-3/references/android/guide/navigation/navigation-3/index.md b/navigation/navigation-3/references/android/guide/navigation/navigation-3/index.md index d567f73..64baf9d 100644 --- a/navigation/navigation-3/references/android/guide/navigation/navigation-3/index.md +++ b/navigation/navigation-3/references/android/guide/navigation/navigation-3/index.md @@ -11,9 +11,9 @@ Use an Android skill to help you build using Jetpack Navigation 3. To install th
Navigation 3 is a new navigation library designed to work with Compose. With -Navigation 3, you have full control over your back stack, and navigating to and -from destinations is as simple as adding and removing items from a list. It -creates a flexible app navigation system by providing: +Navigation 3, you have full control over your back stack, and you navigate to +and from destinations by adding and removing items from a list. It creates a +flexible app navigation system by providing: - Conventions for modeling a back stack, where each entry on the back stack represents content that the user has navigated to - A UI that automatically updates with back stack changes (including animations) @@ -29,6 +29,7 @@ At a high level, you implement Navigation 3 in the following ways: 3. Use a [`NavDisplay`](https://developer.android.com/reference/kotlin/androidx/navigation3/ui/NavDisplay.composable) to display your app's back stack. Whenever the back stack changes, it updates the UI to display relevant content. See [Display the back stack](https://developer.android.com/guide/navigation/navigation-3/basics#display-back). 4. Modify `NavDisplay`'s [scene strategies](https://developer.android.com/guide/navigation/navigation-3/custom-layouts) as needed to support adaptive layouts and different platforms. +5. [Support deep links](https://developer.android.com/guide/navigation/navigation-3/deep-links) to navigate directly to destinations. You can see the [full source code](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:navigation3/) for Navigation 3 on AOSP. @@ -41,8 +42,8 @@ ways: - Offers you full control of the back stack - Makes it possible to create layouts that can read more than one destination from the back stack at the same time, allowing them to adapt to changes in window size and other inputs. -Read more about Navigation 3's principles and API design choices in [this blog -post](https://android-developers.googleblog.com/2025/05/announcing-jetpack-navigation-3-for-compose.html). +Read more about Navigation 3's principles and API design choices in the +[announcement blog post](https://android-developers.googleblog.com/2025/05/announcing-jetpack-navigation-3-for-compose.html). ## Code samples diff --git a/navigation/navigation-3/references/android/guide/navigation/navigation-3/migration-guide.md b/navigation/navigation-3/references/android/guide/navigation/navigation-3/migration-guide.md index 5104177..2e5b216 100644 --- a/navigation/navigation-3/references/android/guide/navigation/navigation-3/migration-guide.md +++ b/navigation/navigation-3/references/android/guide/navigation/navigation-3/migration-guide.md @@ -71,7 +71,7 @@ understand how to implement them. **AI Agent**: Before changing any code, check if the project contains any features supported through recipes. If it does, check the recipe's README and -source code. Create a migration plan based on the recipe. Do not proceed without +source code. Create a migration plan based on the recipe. Don't proceed without confirming the plan with the user. ### Unsupported features @@ -83,10 +83,9 @@ they are just not covered here. - More than one level of nested navigation - Shared destinations: screens that can move between different back stacks - [Custom destination types](https://developer.android.com/guide/navigation/design/kotlin-dsl#custom) -- Deep links **AI Agent**: Before changing any code, check if the project contains any of the -unsupported features. If it does, do not proceed. Inform the user of the +unsupported features. If it does, don't proceed. Inform the user of the unsupported feature and ask for further instructions. ## Step 1: Add Navigation 3 dependencies @@ -254,7 +253,7 @@ fun NavigationState.toEntries(
-**AI Agent** : `rememberSerializable` is correct. Do not change it to +**AI Agent** : `rememberSerializable` is correct. Don't change it to `rememberSaveable`. This file contains a state holder class named `NavigationState` and associated @@ -574,7 +573,93 @@ NavDisplay(
-## Step 7: Remove Navigation 2 dependencies +## Step 7: Migrate deep links + +In Navigation 2, deep links were defined directly inside the navigation graph +using the `deepLinks` parameter of destinations. + +In Navigation 3, deep links are managed independently of the navigation UI. You +define `DeepLinkMatcher`s and match incoming requests in your Activity to +construct the initial back stack. + +Before: + +In Navigation 2, you might have defined a deep link like this: + + +```kotlin +composable( + deepLinks = listOf( + navDeepLink { uriPattern = "www.example.com/user/{id}" } + ) +) { + // ... +} +``` + +
+ +After: + +In Navigation 3, you define a `UriDeepLinkMatcher` for the route: + + +```kotlin +val userMatcher = UriDeepLinkMatcher( + DeepLinkUri("www.example.com/user/{id}"), + serializer() +) +``` + +
+ +Then, in your Activity's `onCreate` (and `onNewIntent`), you match the incoming +intent and initialize your back stack: + + +```kotlin +val deepLinkMatchers: List> = listOf( + userMatcher, +) + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + val request = DeepLinkRequest(intent = intent) + val matchResult = deepLinkMatchers + .mapNotNull { it.match(request) } + .maxOrNull() + + val backStack = when (matchResult) { + null -> listOf(HomeKey) + is BackStackMatchResult<*, *> -> { + @Suppress("UNCHECKED_CAST") + matchResult.backStack as List + } + else -> listOf(matchResult.key) + } + + // Use backStack with NavDisplay + } +} +``` + +
+ +### Custom argument types + +In Navigation 2, you handled custom or third-party argument types (such as +`LocalDateTime`) using custom `NavType` implementations and `typeMap`. + +In Navigation 3, define a [`DeepLinkSerializer`](https://developer.android.com/guide/navigation/navigation-3/deep-links/uri-matcher#deep-link-serializer) to deserialize custom or +third-party types from URI parameters. See +[Custom serialization with DeepLinkSerializer](https://developer.android.com/guide/navigation/navigation-3/deep-links/uri-matcher#deep-link-serializer) for details. + +For more advanced use cases, including synthetic back stacks and custom +matchers, see the [Support deep links](https://developer.android.com/guide/navigation/navigation-3/deep-links) guide. + +## Step 8: Remove Navigation 2 dependencies Remove all Navigation 2 imports and library dependencies. diff --git a/navigation/navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional.md b/navigation/navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional.md index 60848b3..084ad94 100644 --- a/navigation/navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional.md +++ b/navigation/navigation-3/references/android/guide/navigation/navigation-3/recipes/conditional.md @@ -212,12 +212,12 @@ import androidx.navigation3.runtime.NavBackStack * @property isLoggedIn A lambda that returns whether the user is logged in. */ class Navigator( - private val backStack: NavBackStack, - private val onNavigateToRestrictedKey: (targetKey: ConditionalNavKey?) -> ConditionalNavKey, - private val isLoggedIn: () -> Boolean, + private val< backStack: NavBa>ckStackConditionalNavKey, + private val onNavigateToRestrictedKey: (targetKe>y: ConditionalNavKey?) - ConditionalNavKey, + priv>ate val isLoggedIn: () - Boolean, ) { fun navigate(key: ConditionalNavKey) { - if (key.requiresLogin && !isLoggedIn()) { + && if (key.requiresLogin !isLoggedIn()) { val loginKey = onNavigateToRestrictedKey(key) backStack.add(loginKey) } else { @@ -225,6 +225,6 @@ class Navigator( } } - fun goBack() = backStack.removeLastOrNull() -} + fun goBack() = backStstOrNull() +}Navigator.kt ``` \ No newline at end of file diff --git a/navigation/navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-uriarguments.md b/navigation/navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-uriarguments.md deleted file mode 100644 index 2a670b8..0000000 --- a/navigation/navigation-3/references/android/guide/navigation/navigation-3/recipes/deeplinks-uriarguments.md +++ /dev/null @@ -1,390 +0,0 @@ -# Deep Link URI Arguments Recipe - -This recipe demonstrates how to parse a deep link URL from an Android Intent into a Navigation key. - -## Recipe components - -It consists of two activities - -1. `UriWithArgumentsDeepLinkActivity` constructs and triggers the deeplink request -2. `MainActivity` parses the intent into the target navigation key. - -## How it works - -The `MainActivity` handles the request with these steps - -1. Declare a `UriDeepLinkMatcher` for each url pattern that can be deep linked into. Each matcher accepts a uri pattern and the KSerializer of the NavKey that supports this deep link. - -2. Create a `DeepLinkRequest` with the incoming intent. - -3. Match all candidate `UriDeepLinkMatchers` with the request and compare the resulting `UriMatchResults` for the best match. - -4. Read the matching key from `UriMatchResult.key` or use default key if no match. - -This recipe focuses on handing an intent and does not include these considerations: - -- Create synthetic backStack -- Multi-modular setup -- DI -- Managing TaskStack -- Up button vs Back Button - -## Demonstrated forms of deeplink - -The `MainActivity` has several backStack keys to demonstrate different types of supported deep links: - -1. `HomeKey` - deeplink with an exact url (no deeplink arguments) -2. `UsersKey` - deeplink with path arguments -3. `SearchKey` - deeplink with query arguments - -See `MainActivity.deepLinkMatchers` for the actual url pattern of each. -[![](https://developer.android.com/static/images/picto-icons/code.svg) Explore View the full recipe on GitHub.](https://github.com/android/nav3-recipes/tree/main/app/src/main/java/com/example/nav3recipes/deeplink/handlerequests/uriarguments) - -``` -package com.example.nav3recipes.deeplink.handlerequests.uriarguments - -import androidx.navigation3.runtime.NavKey -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.STRING_LITERAL_FILTER -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.STRING_LITERAL_HOME -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.STRING_LITERAL_SEARCH -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.STRING_LITERAL_USERS -import kotlinx.serialization.Serializable - -internal interface NavRecipeKey: NavKey { - val name: String -} - -@Serializable -internal object HomeKey: NavRecipeKey { - override val name: String = STRING_LITERAL_HOME -} - -@Serializable -internal data class UsersKey( - val filter: String, -): NavRecipeKey { - override val name: String = STRING_LITERAL_USERS - companion object { - const val FILTER_KEY = STRING_LITERAL_FILTER - const val FILTER_OPTION_RECENTLY_ADDED = "recentlyAdded" - const val FILTER_OPTION_ALL = "all" - } -} - -@Serializable -internal data class SearchKey( - val firstName: String? = null, - val ageMin: Int? = null, - val ageMax: Int? = null, - val location: String? = null, -): NavRecipeKey { - override val name: String = STRING_LITERAL_SEARCH -} -``` - -``` -package com.example.nav3recipes.deeplink.handlerequests.uriarguments - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.core.net.toUri -import androidx.navigation3.runtime.NavBackStack -import androidx.navigation3.runtime.NavKey -import androidx.navigation3.runtime.deeplink.DeepLinkRequest -import androidx.navigation3.runtime.deeplink.UriDeepLinkMatcher -import androidx.navigation3.runtime.deeplink.invoke -import androidx.navigation3.runtime.entryProvider -import androidx.navigation3.runtime.rememberNavBackStack -import androidx.navigation3.ui.NavDisplay -import com.example.nav3recipes.common.deeplink.EntryScreen -import com.example.nav3recipes.common.deeplink.FriendsList -import com.example.nav3recipes.common.deeplink.LIST_USERS -import com.example.nav3recipes.common.deeplink.TextContent -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.URL_HOME_EXACT -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.URL_SEARCH -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.URL_USERS_WITH_FILTER -import com.example.nav3recipes.ui.setEdgeToEdgeConfig -import kotlinx.serialization.serializer - -/** - * See README.md for how this recipe works. - */ -class MainActivity : ComponentActivity() { - /** STEP 1. Declare supported deep links */ - internal val deepLinkMatchers: List> = listOf( - // "https://www.nav3recipes.com/home" - UriDeepLinkMatcher(URL_HOME_EXACT.toUri(), serializer()), - // "https://www.nav3recipes.com/users/with/{filter}" - UriDeepLinkMatcher(URL_USERS_WITH_FILTER.toUri(), serializer()), - // "https://www.nav3recipes.com/users/search?{firstName}&{age}&{location}" - UriDeepLinkMatcher(URL_SEARCH.toUri(), serializer()), - ) - - override fun onCreate(savedInstanceState: Bundle?) { - setEdgeToEdgeConfig() - super.onCreate(savedInstanceState) - - /** STEP 2. Create a [DeepLinkRequest] from the intent */ - val request = DeepLinkRequest(intent) - - /** STEP 3. Match the request to the DeepLinkMatchers*/ - // First get all the possible matching UriMatchResult - val matches = deepLinkMatchers.mapNotNull { - // returns null if no match - it.match(request) - } - // compare all matches to find best match - val bestMatch = matches.maxOrNull() - /** STEP 4. Get the key from the match or use default key if no match*/ - val key = bestMatch?.key ?: HomeKey - - /** - * STEP 5. pass the initial key to backstack - */ - setContent { - val backStack: NavBackStack = rememberNavBackStack(key) - NavDisplay( - backStack = backStack, - onBack = { backStack.removeLastOrNull() }, - entryProvider = entryProvider { - entry { key -> - EntryScreen(key.name) { - TextContent("") - } - } - entry { key -> - EntryScreen("${key.name} : ${key.filter}") { - TextContent("") - val list = when { - key.filter.isEmpty() -> LIST_USERS - key.filter == UsersKey.FILTER_OPTION_ALL -> LIST_USERS - else -> LIST_USERS.take(5) - } - FriendsList(list) - } - } - entry { search -> - EntryScreen(search.name) { - TextContent("") - val matchingUsers = LIST_USERS.filter { user -> - (search.firstName == null || user.firstName == search.firstName) && - (search.location == null || user.location == search.location) && - (search.ageMin == null || user.age >= search.ageMin) && - (search.ageMax == null || user.age <= search.ageMax) - } - FriendsList(matchingUsers) - } - } - } - ) - } - } -} -``` - -``` -package com.example.nav3recipes.deeplink.handlerequests.uriarguments - -import android.content.Intent -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateMapOf -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.core.net.toUri -import androidx.lifecycle.compose.dropUnlessResumed -import com.example.nav3recipes.common.deeplink.EMPTY -import com.example.nav3recipes.common.deeplink.EntryScreen -import com.example.nav3recipes.common.deeplink.FIRST_NAME_JOHN -import com.example.nav3recipes.common.deeplink.FIRST_NAME_JULIE -import com.example.nav3recipes.common.deeplink.FIRST_NAME_MARY -import com.example.nav3recipes.common.deeplink.FIRST_NAME_TOM -import com.example.nav3recipes.common.deeplink.LOCATION_BC -import com.example.nav3recipes.common.deeplink.LOCATION_BR -import com.example.nav3recipes.common.deeplink.LOCATION_CA -import com.example.nav3recipes.common.deeplink.LOCATION_US -import com.example.nav3recipes.common.deeplink.MenuDropDown -import com.example.nav3recipes.common.deeplink.MenuTextInput -import com.example.nav3recipes.common.deeplink.PaddedButton -import com.example.nav3recipes.common.deeplink.TextContent -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.PATH_BASE -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.PATH_INCLUDE -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.PATH_SEARCH -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui.STRING_LITERAL_HOME -import com.example.nav3recipes.ui.setEdgeToEdgeConfig - -/** - * See README.md for how this recipe works. - * - * See [MainActivity] for how the requested deeplink is handled. - */ -class UriWithArgumentsDeepLinkActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - setEdgeToEdgeConfig() - super.onCreate(savedInstanceState) - - setContent { - /** - * UI for deeplink sandbox - */ - EntryScreen("Sandbox - Build Your Deeplink") { - TextContent("Base url:\n${PATH_BASE}/") - var showFilterOptions by remember { mutableStateOf(false) } - val selectedPath = remember { mutableStateOf(MENU_OPTIONS_PATH[KEY_PATH]?.first()) } - - var showQueryOptions by remember { mutableStateOf(false) } - var selectedFilter by remember { mutableStateOf("") } - val selectedSearchQuery = remember { mutableStateMapOf() } - - // manage path options - MenuDropDown( - menuOptions = MENU_OPTIONS_PATH, - ) { _, selection -> - selectedPath.value = selection - when (selection) { - PATH_SEARCH -> { - showQueryOptions = true - showFilterOptions = false - } - - PATH_INCLUDE -> { - showQueryOptions = false - showFilterOptions = true - } - - else -> { - showQueryOptions = false - showFilterOptions = false - } - } - } - - // manage path filter options, reset state if menu is closed - LaunchedEffect(showFilterOptions) { - selectedFilter = if (showFilterOptions) { - MENU_OPTIONS_FILTER.values.first().first() - } else { - "" - } - } - if (showFilterOptions) { - MenuDropDown( - menuOptions = MENU_OPTIONS_FILTER, - ) { _, selected -> - selectedFilter = selected - } - } - - // manage query options, reset state if menu is closed - LaunchedEffect(showQueryOptions) { - if (showQueryOptions) { - val initEntry = MENU_OPTIONS_SEARCH.entries.first() - selectedSearchQuery[initEntry.key] = initEntry.value.first() - } else { - selectedSearchQuery.clear() - } - } - if (showQueryOptions) { - MenuTextInput( - menuLabels = MENU_LABELS_SEARCH, - ) { label, selected -> - selectedSearchQuery[label] = selected - } - MenuDropDown( - menuOptions = MENU_OPTIONS_SEARCH, - ) { label, selected -> - selectedSearchQuery[label] = selected - } - } - - // form final deeplink url - val arguments = when (selectedPath.value) { - PATH_INCLUDE -> "/${selectedFilter}" - PATH_SEARCH -> { - buildString { - selectedSearchQuery.forEach { entry -> - if (entry.value.isNotEmpty()) { - val prefix = if (isEmpty()) "?" else "&" - append("$prefix${entry.key}=${entry.value}") - } - } - } - } - - else -> "" - } - val finalUrl = "${PATH_BASE}/${selectedPath.value}$arguments" - TextContent("Final url:\n$finalUrl") - // deeplink to target - PaddedButton("Deeplink Away!", onClick = dropUnlessResumed { - val intent = Intent( - this@UriWithArgumentsDeepLinkActivity, - MainActivity::class.java - ) - // start activity with the url - intent.data = finalUrl.toUri() - startActivity(intent) - }) - } - } - } -} - -private const val KEY_PATH = "path" -private val MENU_OPTIONS_PATH = mapOf( - KEY_PATH to listOf( - STRING_LITERAL_HOME, - PATH_INCLUDE, - PATH_SEARCH, - ), -) - -private val MENU_OPTIONS_FILTER = mapOf( - UsersKey.FILTER_KEY to listOf(UsersKey.FILTER_OPTION_RECENTLY_ADDED, UsersKey.FILTER_OPTION_ALL), -) - -private val MENU_OPTIONS_SEARCH = mapOf( - SearchKey::firstName.name to listOf( - EMPTY, - FIRST_NAME_JOHN, - FIRST_NAME_TOM, - FIRST_NAME_MARY, - FIRST_NAME_JULIE - ), - SearchKey::location.name to listOf(EMPTY, LOCATION_CA, LOCATION_BC, LOCATION_BR, LOCATION_US) -) - -private val MENU_LABELS_SEARCH = listOf(SearchKey::ageMin.name, SearchKey::ageMax.name) - -``` - -``` -package com.example.nav3recipes.deeplink.handlerequests.uriarguments.ui - -import com.example.nav3recipes.deeplink.handlerequests.uriarguments.SearchKey - -/** - * String resources - */ -internal const val STRING_LITERAL_FILTER = "filter" -internal const val STRING_LITERAL_HOME = "home" -internal const val STRING_LITERAL_USERS = "users" -internal const val STRING_LITERAL_SEARCH = "search" -internal const val STRING_LITERAL_INCLUDE = "include" -internal const val PATH_BASE = "https://www.nav3recipes.com" -internal const val PATH_INCLUDE = "$STRING_LITERAL_USERS/$STRING_LITERAL_INCLUDE" -internal const val PATH_SEARCH = "$STRING_LITERAL_USERS/$STRING_LITERAL_SEARCH" -internal const val URL_HOME_EXACT = "$PATH_BASE/$STRING_LITERAL_HOME" - -internal const val URL_USERS_WITH_FILTER = "$PATH_BASE/$PATH_INCLUDE/{$STRING_LITERAL_FILTER}" -internal val URL_SEARCH = "$PATH_BASE/$PATH_SEARCH" + - "?${SearchKey::ageMin.name}={${SearchKey::ageMin.name}}" + - "&${SearchKey::ageMax.name}={${SearchKey::ageMax.name}}" + - "&${SearchKey::firstName.name}={${SearchKey::firstName.name}}" + - "&${SearchKey::location.name}={${SearchKey::location.name}}" -``` \ No newline at end of file diff --git a/wear/wear-compose-m3/SKILL.md b/wear/wear-compose-m3/SKILL.md index 1a71c4d..95ae311 100644 --- a/wear/wear-compose-m3/SKILL.md +++ b/wear/wear-compose-m3/SKILL.md @@ -5,11 +5,12 @@ description: Expert guidance for working with Wear OS Compose Material3. Use thi androidx.wear.compose.material3, androidx.wear.compose.foundation, and androidx.wear.compose.navigation3 libraries. Also working with core components such as AppScaffold, ScreenScaffold, and TransformingLazyColumn, and core Wear OS concepts such as ambient mode. Migration - from lower versions such as Material 2.5 and Horologist. + from lower versions such as Material 2.5 and Horologist. This also includes creating + previews. license: Complete terms in LICENSE.txt metadata: author: Google LLC - last-updated: '2026-09-03' + last-updated: '2026-09-10' keywords: - Wear OS - Compose @@ -81,10 +82,10 @@ from the table to ensure you know how to correctly use it. | `AppCard` | [CardSample](references/material3/CardSample.kt.md.txt) | | `AppScaffold` | [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [PagerScaffoldSample](references/material3/PagerScaffoldSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `ArcProgressIndicator`, `ArcProgressIndicatorDefaults`, `CircularProgressIndicator`, `CircularProgressIndicatorDefaults`, `ProgressIndicatorDefaults`, `SegmentedCircularProgressIndicator`, `drawCircularProgressIndicator` | [ProgressIndicatorSample](references/material3/ProgressIndicatorSample.kt.md.txt) | -| `Button` | [AlertDialogSample](references/material3/AlertDialogSample.kt.md.txt), [AnimatedTextSample](references/material3/AnimatedTextSample.kt.md.txt), [ButtonGroupSample](references/material3/ButtonGroupSample.kt.md.txt), [ButtonSample](references/material3/ButtonSample.kt.md.txt), [DatePickerSample](references/material3/DatePickerSample.kt.md.txt), [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [FadingExpandingLabelSample](references/material3/FadingExpandingLabelSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [PageIndicatorSample](references/material3/PageIndicatorSample.kt.md.txt), [PagerScaffoldSample](references/material3/PagerScaffoldSample.kt.md.txt), [PickerSample](references/material3/PickerSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [StepperSample](references/material3/StepperSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TimePickerSample](references/material3/TimePickerSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `Button` | [AlertDialogSample](references/material3/AlertDialogSample.kt.md.txt), [AnimatedTextSample](references/material3/AnimatedTextSample.kt.md.txt), [ButtonGroupSample](references/material3/ButtonGroupSample.kt.md.txt), [ButtonSample](references/material3/ButtonSample.kt.md.txt), [DatePickerSample](references/material3/DatePickerSample.kt.md.txt), [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [FadingExpandingLabelSample](references/material3/FadingExpandingLabelSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [PageIndicatorSample](references/material3/PageIndicatorSample.kt.md.txt), [PagerScaffoldSample](references/material3/PagerScaffoldSample.kt.md.txt), [PickerSample](references/material3/PickerSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [StepperSample](references/material3/StepperSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TimePickerSample](references/material3/TimePickerSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `ButtonDefaults` | [ButtonSample](references/material3/ButtonSample.kt.md.txt), [CurvedTextSamples](references/material3/CurvedTextSamples.kt.md.txt), [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [EdgeButtonSample](references/material3/EdgeButtonSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [PlaceholderSample](references/material3/PlaceholderSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [TextButtonSample](references/material3/TextButtonSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `ButtonGroup` | [ButtonGroupSample](references/material3/ButtonGroupSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt) | -| `Card` | [CardSample](references/material3/CardSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `Card` | [CardSample](references/material3/CardSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `CardDefaults` | [CardSample](references/material3/CardSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `CheckboxButton` | [CheckboxButtonSample](references/material3/CheckboxButtonSample.kt.md.txt), [SwipeToDismissBoxSample](references/material3/SwipeToDismissBoxSample.kt.md.txt) | | `ChildButton`, `OutlinedButton` | [ButtonSample](references/material3/ButtonSample.kt.md.txt) | @@ -93,7 +94,7 @@ from the table to ensure you know how to correctly use it. | `ConfirmationDialog`, `ConfirmationDialogDefaults`, `FailureConfirmationDialog`, `FavoriteIcon`, `SuccessConfirmationDialog`, `confirmationDialogCurvedText` | [ConfirmationDialogSample](references/material3/ConfirmationDialogSample.kt.md.txt) | | `CurvedTextDefaults` | [CurvedTextSamples](references/material3/CurvedTextSamples.kt.md.txt) | | `DatePicker`, `DatePickerType` | [DatePickerSample](references/material3/DatePickerSample.kt.md.txt) | -| `EdgeButton` | [EdgeButtonSample](references/material3/EdgeButtonSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `EdgeButton` | [EdgeButtonSample](references/material3/EdgeButtonSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `EdgeButtonSize` | [EdgeButtonSample](references/material3/EdgeButtonSample.kt.md.txt) | | `FadingExpandingLabel` | [FadingExpandingLabelSample](references/material3/FadingExpandingLabelSample.kt.md.txt) | | `FilledIconButton`, `FilledTonalIconButton`, `IconButtonColors`, `IconButtonShapes`, `OutlinedIconButton` | [IconButtonSample](references/material3/IconButtonSample.kt.md.txt) | @@ -106,7 +107,7 @@ from the table to ensure you know how to correctly use it. | `IconToggleButton`, `IconToggleButtonDefaults`, `WifiOffIcon`, `WifiOnIcon` | [IconToggleButtonSample](references/material3/IconToggleButtonSample.kt.md.txt) | | `LevelIndicator` | [LevelIndicatorSample](references/material3/LevelIndicatorSample.kt.md.txt) | | `LinearProgressIndicator` | [LinearProgressIndicatorSample](references/material3/LinearProgressIndicatorSample.kt.md.txt) | -| `ListHeader` | [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `ListHeader` | [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `ListHeaderDefaults` | [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `ListSubHeader` | [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt) | | `LocalOneHandedGestureEnabled`, `OneHandedGestureDefaults`, `OneHandedGestureHorizontalPageIndicator`, `OneHandedGesturePageIndicatorState`, `OneHandedGesturePriority`, `OneHandedGestureScrollIndicator`, `OneHandedGestureScrollIndicatorState`, `OneHandedGestureVerticalPageIndicator` | [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt) | @@ -120,30 +121,30 @@ from the table to ensure you know how to correctly use it. | `RadioButton`, `SplitRadioButton` | [RadioButtonSample](references/material3/RadioButtonSample.kt.md.txt) | | `ResponsiveTransformationSpec`, `TransformationVariableSpec` | [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt) | | `RevealValue`, `SwipeToReveal`, `SwipeToRevealDefaults`, `rememberRevealState` | [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt) | -| `ScreenScaffold` | [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [PagerScaffoldSample](references/material3/PagerScaffoldSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `ScreenScaffold` | [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [PagerScaffoldSample](references/material3/PagerScaffoldSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `ScreenScaffoldDefaults`, `ScrollIndicator` | [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt) | | `ScreenStage`, `scrollAway` | [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt) | | `Slider`, `SliderDefaults` | [SliderSample](references/material3/SliderSample.kt.md.txt) | | `SplitCheckboxButton` | [CheckboxButtonSample](references/material3/CheckboxButtonSample.kt.md.txt) | | `SplitSwitchButton` | [SwitchButtonSample](references/material3/SwitchButtonSample.kt.md.txt) | | `StepperDefaults`, `VolumeDownIcon`, `VolumeUpIcon` | [LevelIndicatorSample](references/material3/LevelIndicatorSample.kt.md.txt), [StepperSample](references/material3/StepperSample.kt.md.txt) | -| `SurfaceTransformation` | [AlertDialogSample](references/material3/AlertDialogSample.kt.md.txt), [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `SurfaceTransformation` | [AlertDialogSample](references/material3/AlertDialogSample.kt.md.txt), [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `SwipeToDismissBox` | [SwipeToDismissBoxSample](references/material3/SwipeToDismissBoxSample.kt.md.txt) | | `SwitchButton` | [AlertDialogSample](references/material3/AlertDialogSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [SwitchButtonSample](references/material3/SwitchButtonSample.kt.md.txt) | -| `Text` | [AlertDialogSample](references/material3/AlertDialogSample.kt.md.txt), [AnimatedTextSample](references/material3/AnimatedTextSample.kt.md.txt), [ButtonGroupSample](references/material3/ButtonGroupSample.kt.md.txt), [ButtonSample](references/material3/ButtonSample.kt.md.txt), [CardSample](references/material3/CardSample.kt.md.txt), [CheckboxButtonSample](references/material3/CheckboxButtonSample.kt.md.txt), [ConfirmationDialogSample](references/material3/ConfirmationDialogSample.kt.md.txt), [DatePickerSample](references/material3/DatePickerSample.kt.md.txt), [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [EdgeButtonSample](references/material3/EdgeButtonSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [OpenOnPhoneDialogSample](references/material3/OpenOnPhoneDialogSample.kt.md.txt), [PageIndicatorSample](references/material3/PageIndicatorSample.kt.md.txt), [PagerScaffoldSample](references/material3/PagerScaffoldSample.kt.md.txt), [PickerGroupSample](references/material3/PickerGroupSample.kt.md.txt), [PickerSample](references/material3/PickerSample.kt.md.txt), [PlaceholderSample](references/material3/PlaceholderSample.kt.md.txt), [RadioButtonSample](references/material3/RadioButtonSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [StepperSample](references/material3/StepperSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeToDismissBoxSample](references/material3/SwipeToDismissBoxSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [SwitchButtonSample](references/material3/SwitchButtonSample.kt.md.txt), [TextButtonSample](references/material3/TextButtonSample.kt.md.txt), [TextToggleButtonSample](references/material3/TextToggleButtonSample.kt.md.txt), [TimePickerSample](references/material3/TimePickerSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `Text` | [AlertDialogSample](references/material3/AlertDialogSample.kt.md.txt), [AnimatedTextSample](references/material3/AnimatedTextSample.kt.md.txt), [ButtonGroupSample](references/material3/ButtonGroupSample.kt.md.txt), [ButtonSample](references/material3/ButtonSample.kt.md.txt), [CardSample](references/material3/CardSample.kt.md.txt), [CheckboxButtonSample](references/material3/CheckboxButtonSample.kt.md.txt), [ConfirmationDialogSample](references/material3/ConfirmationDialogSample.kt.md.txt), [DatePickerSample](references/material3/DatePickerSample.kt.md.txt), [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [EdgeButtonSample](references/material3/EdgeButtonSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [OpenOnPhoneDialogSample](references/material3/OpenOnPhoneDialogSample.kt.md.txt), [PageIndicatorSample](references/material3/PageIndicatorSample.kt.md.txt), [PagerScaffoldSample](references/material3/PagerScaffoldSample.kt.md.txt), [PickerGroupSample](references/material3/PickerGroupSample.kt.md.txt), [PickerSample](references/material3/PickerSample.kt.md.txt), [PlaceholderSample](references/material3/PlaceholderSample.kt.md.txt), [RadioButtonSample](references/material3/RadioButtonSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [StepperSample](references/material3/StepperSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [SwipeToDismissBoxSample](references/material3/SwipeToDismissBoxSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [SwitchButtonSample](references/material3/SwitchButtonSample.kt.md.txt), [TextButtonSample](references/material3/TextButtonSample.kt.md.txt), [TextToggleButtonSample](references/material3/TextToggleButtonSample.kt.md.txt), [TimePickerSample](references/material3/TimePickerSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `TextButton` | [TextButtonSample](references/material3/TextButtonSample.kt.md.txt) | | `TextButtonDefaults` | [TextButtonSample](references/material3/TextButtonSample.kt.md.txt), [TextToggleButtonSample](references/material3/TextToggleButtonSample.kt.md.txt) | | `TextToggleButton`, `TextToggleButtonDefaults`, `touchTargetAwareSize` | [TextToggleButtonSample](references/material3/TextToggleButtonSample.kt.md.txt) | | `TimePicker`, `TimePickerType` | [TimePickerSample](references/material3/TimePickerSample.kt.md.txt) | | `TimeText` | [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [TimeTextSample](references/material3/TimeTextSample.kt.md.txt) | | `TimeTextDefaults`, `timeTextCurvedText` | [TimeTextSample](references/material3/TimeTextSample.kt.md.txt) | -| `TitleCard` | [CardSample](references/material3/CardSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt) | +| `TitleCard` | [CardSample](references/material3/CardSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt) | | `TransformationSpec` | [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt) | | `curvedText` | [CurvedTextSamples](references/material3/CurvedTextSamples.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [TimeTextSample](references/material3/TimeTextSample.kt.md.txt) | | `firstVisibleItemLayoutItemInfo`, `layoutItemInfoOf`, `rememberTransformingLazyColumnFirstLayoutItemProvider` | [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `placeholder`, `placeholderShimmer`, `rememberPlaceholderState` | [PlaceholderSample](references/material3/PlaceholderSample.kt.md.txt) | | `rememberPickerState` | [PickerGroupSample](references/material3/PickerGroupSample.kt.md.txt), [PickerSample](references/material3/PickerSample.kt.md.txt) | -| `rememberTransformationSpec`, `transformedHeight` | [AlertDialogSample](references/material3/AlertDialogSample.kt.md.txt), [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `rememberTransformationSpec`, `transformedHeight` | [AlertDialogSample](references/material3/AlertDialogSample.kt.md.txt), [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `timeTextSeparator` | [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [TimeTextSample](references/material3/TimeTextSample.kt.md.txt) | #### Foundation components in `androidx.wear.compose.foundation.*` @@ -166,19 +167,25 @@ from the table to ensure you know how to correctly use it. | `ScalingLazyColumn` | [ExpandableSample](references/foundation/ExpandableSample.kt.md.txt), [HierarchicalFocusSample](references/foundation/HierarchicalFocusSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [ScalingLazyColumnSample](references/foundation/ScalingLazyColumnSample.kt.md.txt), [SwipeToRevealSample](references/foundation/SwipeToRevealSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt) | | `ScrollInfoProvider` | [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt) | | `SwipeToDismissValue`, `edgeSwipeToDismiss`, `rememberSwipeToDismissBoxState` | [SwipeToDismissBoxSample](references/foundation/SwipeToDismissBoxSample.kt.md.txt), [SwipeToDismissBoxSample](references/material3/SwipeToDismissBoxSample.kt.md.txt) | -| `TransformingLazyColumn` | [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `TransformingLazyColumn` | [DynamicColorSchemeSample](references/material3/DynamicColorSchemeSample.kt.md.txt), [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `TransformingLazyColumnFirstLayoutItemProvider` | [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `TransformingLazyColumnItemScrollProgress` | [TransformationSpecSample](references/material3/TransformationSpecSample.kt.md.txt) | | `expandableButton`, `expandableItems` | [ExpandableSample](references/foundation/ExpandableSample.kt.md.txt) | | `expandableItem`, `rememberExpandableState` | [ExpandableSample](references/foundation/ExpandableSample.kt.md.txt), [SwipeToRevealSample](references/foundation/SwipeToRevealSample.kt.md.txt) | | `hierarchicalFocusGroup` | [HierarchicalFocusSample](references/foundation/HierarchicalFocusSample.kt.md.txt) | -| `items` | [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt) | +| `items` | [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt) | | `itemsIndexed` | [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `rememberScalingLazyListState` | [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [ScalingLazyColumnSample](references/foundation/ScalingLazyColumnSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt) | -| `rememberTransformingLazyColumnState` | [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | +| `rememberTransformingLazyColumnState` | [ListHeaderSample](references/material3/ListHeaderSample.kt.md.txt), [OneHandedGestureSamples](references/material3/OneHandedGestureSamples.kt.md.txt), [ScaffoldSample](references/material3/ScaffoldSample.kt.md.txt), [ScrollAwaySample](references/material3/ScrollAwaySample.kt.md.txt), [ScrollIndicatorSample](references/material3/ScrollIndicatorSample.kt.md.txt), [SurfaceTransformationSample](references/material3/SurfaceTransformationSample.kt.md.txt), [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt), [SwipeToRevealSample](references/material3/SwipeToRevealSample.kt.md.txt), [TransformingLazyColumnNotificationsSample](references/material3/TransformingLazyColumnNotificationsSample.kt.md.txt), [TransformingLazyColumnSample](references/foundation/TransformingLazyColumnSample.kt.md.txt), [TransformingLazyColumnSample](references/material3/TransformingLazyColumnSample.kt.md.txt) | | `requestFocusOnHierarchyActive` | [HierarchicalFocusSample](references/foundation/HierarchicalFocusSample.kt.md.txt), [RotarySamples](references/foundation/RotarySamples.kt.md.txt) | | `weight` | [CurvedWorldSample](references/foundation/CurvedWorldSample.kt.md.txt), [TimeTextSample](references/material3/TimeTextSample.kt.md.txt) | +#### Navigation 3 components in `androidx.wear.compose.navigation3.*` + +| Component / Symbol | Reference Samples | +|---|---| +| `rememberSwipeDismissableSceneStrategy` | [SwipeDismissableSceneStrategySample](references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt) | + ### Capability 4: Component guidance **Mandatory**: Use this capability as a checklist against any component use. It @@ -335,10 +342,11 @@ the component syntax. - \[ \] Components such as `Button` have a corresponding `ButtonDefaults` object. - \[ \] Check for and use the `*Defaults` object for any component when working with padding and styling values, in preference to hard-coded values. -9. Use Wear specific previews: +9. Use Wear-specific preview annotations: - - \[ \] `WearPreviewDevices` - - \[ \] `WearPreviewFontScales` + - \[ \] `@WearPreviewDevices` + - \[ \] `@WearPreviewFontScales` + - \[ \] Ensure the `androidx.wear.compose:compose-ui-tooling` dependency is included. 10. Ambient mode - \[ \] Use `LocalAmbientModeManager` instead of `AmbientLifecycleObserver`. diff --git a/wear/wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md b/wear/wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md index 46ecc1b..bfe0fb1 100644 --- a/wear/wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md +++ b/wear/wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md @@ -107,7 +107,8 @@ fun StatefulSwipeToDismissBox() { Column( modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp), - verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically), + verticalArrangement = + Arrangement.spacedBy(4.dp, Alignment.CenterVertically), ) { SplitToggleChip( checked = checked.value, diff --git a/wear/wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md.txt b/wear/wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md.txt index 46ecc1b..bfe0fb1 100644 --- a/wear/wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md.txt +++ b/wear/wear-compose-m3/references/foundation/SwipeToDismissBoxSample.kt.md.txt @@ -107,7 +107,8 @@ fun StatefulSwipeToDismissBox() { Column( modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp), - verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically), + verticalArrangement = + Arrangement.spacedBy(4.dp, Alignment.CenterVertically), ) { SplitToggleChip( checked = checked.value, diff --git a/wear/wear-compose-m3/references/material3/CheckboxButtonSample.kt.md b/wear/wear-compose-m3/references/material3/CheckboxButtonSample.kt.md index 3ae73bd..22af708 100644 --- a/wear/wear-compose-m3/references/material3/CheckboxButtonSample.kt.md +++ b/wear/wear-compose-m3/references/material3/CheckboxButtonSample.kt.md @@ -59,9 +59,7 @@ fun SplitCheckboxButtonSample() { checked = checked, onCheckedChange = { checked = it }, toggleContentDescription = "Split Checkbox Button Sample", - onContainerClick = { - /* Do something */ - }, + onContainerClick = { /* Do something */ }, containerClickLabel = "click", enabled = true, ) diff --git a/wear/wear-compose-m3/references/material3/CheckboxButtonSample.kt.md.txt b/wear/wear-compose-m3/references/material3/CheckboxButtonSample.kt.md.txt index 3ae73bd..22af708 100644 --- a/wear/wear-compose-m3/references/material3/CheckboxButtonSample.kt.md.txt +++ b/wear/wear-compose-m3/references/material3/CheckboxButtonSample.kt.md.txt @@ -59,9 +59,7 @@ fun SplitCheckboxButtonSample() { checked = checked, onCheckedChange = { checked = it }, toggleContentDescription = "Split Checkbox Button Sample", - onContainerClick = { - /* Do something */ - }, + onContainerClick = { /* Do something */ }, containerClickLabel = "click", enabled = true, ) diff --git a/wear/wear-compose-m3/references/material3/PlaceholderSample.kt.md b/wear/wear-compose-m3/references/material3/PlaceholderSample.kt.md index 943bca1..b7f8c9e 100644 --- a/wear/wear-compose-m3/references/material3/PlaceholderSample.kt.md +++ b/wear/wear-compose-m3/references/material3/PlaceholderSample.kt.md @@ -170,7 +170,9 @@ fun TextPlaceholder() { overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Center, modifier = - Modifier.width(90.dp).placeholderShimmer(placeholderState).placeholder(placeholderState), + Modifier.width(90.dp) + .placeholderShimmer(placeholderState) + .placeholder(placeholderState), ) // Simulate content loading diff --git a/wear/wear-compose-m3/references/material3/PlaceholderSample.kt.md.txt b/wear/wear-compose-m3/references/material3/PlaceholderSample.kt.md.txt index 943bca1..b7f8c9e 100644 --- a/wear/wear-compose-m3/references/material3/PlaceholderSample.kt.md.txt +++ b/wear/wear-compose-m3/references/material3/PlaceholderSample.kt.md.txt @@ -170,7 +170,9 @@ fun TextPlaceholder() { overflow = TextOverflow.Ellipsis, textAlign = TextAlign.Center, modifier = - Modifier.width(90.dp).placeholderShimmer(placeholderState).placeholder(placeholderState), + Modifier.width(90.dp) + .placeholderShimmer(placeholderState) + .placeholder(placeholderState), ) // Simulate content loading diff --git a/wear/wear-compose-m3/references/material3/RadioButtonSample.kt.md b/wear/wear-compose-m3/references/material3/RadioButtonSample.kt.md index 3c1b941..48e4944 100644 --- a/wear/wear-compose-m3/references/material3/RadioButtonSample.kt.md +++ b/wear/wear-compose-m3/references/material3/RadioButtonSample.kt.md @@ -84,9 +84,7 @@ fun SplitRadioButtonSample() { selected = selectedButton == 0, onSelectionClick = { selectedButton = 0 }, selectionContentDescription = "First", - onContainerClick = { - /* Do something */ - }, + onContainerClick = { /* Do something */ }, containerClickLabel = "click", modifier = Modifier.fillMaxWidth(), enabled = true, @@ -97,9 +95,7 @@ fun SplitRadioButtonSample() { selected = selectedButton == 1, onSelectionClick = { selectedButton = 1 }, selectionContentDescription = "Second", - onContainerClick = { - /* Do something */ - }, + onContainerClick = { /* Do something */ }, containerClickLabel = "click", modifier = Modifier.fillMaxWidth(), enabled = true, diff --git a/wear/wear-compose-m3/references/material3/RadioButtonSample.kt.md.txt b/wear/wear-compose-m3/references/material3/RadioButtonSample.kt.md.txt index 3c1b941..48e4944 100644 --- a/wear/wear-compose-m3/references/material3/RadioButtonSample.kt.md.txt +++ b/wear/wear-compose-m3/references/material3/RadioButtonSample.kt.md.txt @@ -84,9 +84,7 @@ fun SplitRadioButtonSample() { selected = selectedButton == 0, onSelectionClick = { selectedButton = 0 }, selectionContentDescription = "First", - onContainerClick = { - /* Do something */ - }, + onContainerClick = { /* Do something */ }, containerClickLabel = "click", modifier = Modifier.fillMaxWidth(), enabled = true, @@ -97,9 +95,7 @@ fun SplitRadioButtonSample() { selected = selectedButton == 1, onSelectionClick = { selectedButton = 1 }, selectionContentDescription = "Second", - onContainerClick = { - /* Do something */ - }, + onContainerClick = { /* Do something */ }, containerClickLabel = "click", modifier = Modifier.fillMaxWidth(), enabled = true, diff --git a/wear/wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md b/wear/wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md index 6b3b7fa..436bde1 100644 --- a/wear/wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md +++ b/wear/wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md @@ -19,6 +19,7 @@ package androidx.wear.compose.material3.samples import androidx.annotation.Sampled import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape @@ -64,13 +65,13 @@ fun SurfaceTransformationOnCustomComponent() { modifier = modifier .fillMaxWidth() + .graphicsLayer { with(transformation) { applyContainerTransformation() } } .paint( transformation.createContainerPainter( ColorPainter(color = Color.Gray), shape = RoundedCornerShape(16.dp), ) ) - .graphicsLayer { with(transformation) { applyContainerTransformation() } } .padding(horizontal = 16.dp, vertical = 8.dp) ) { Text(title) @@ -80,7 +81,7 @@ fun SurfaceTransformationOnCustomComponent() { val transformationSpec = rememberTransformationSpec() - TransformingLazyColumn { + TransformingLazyColumn(contentPadding = PaddingValues(horizontal = 10.dp)) { items(count = 100) { MyCardComponent( "Message #$it", diff --git a/wear/wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md.txt b/wear/wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md.txt index 6b3b7fa..436bde1 100644 --- a/wear/wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md.txt +++ b/wear/wear-compose-m3/references/material3/SurfaceTransformationSample.kt.md.txt @@ -19,6 +19,7 @@ package androidx.wear.compose.material3.samples import androidx.annotation.Sampled import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape @@ -64,13 +65,13 @@ fun SurfaceTransformationOnCustomComponent() { modifier = modifier .fillMaxWidth() + .graphicsLayer { with(transformation) { applyContainerTransformation() } } .paint( transformation.createContainerPainter( ColorPainter(color = Color.Gray), shape = RoundedCornerShape(16.dp), ) ) - .graphicsLayer { with(transformation) { applyContainerTransformation() } } .padding(horizontal = 16.dp, vertical = 8.dp) ) { Text(title) @@ -80,7 +81,7 @@ fun SurfaceTransformationOnCustomComponent() { val transformationSpec = rememberTransformationSpec() - TransformingLazyColumn { + TransformingLazyColumn(contentPadding = PaddingValues(horizontal = 10.dp)) { items(count = 100) { MyCardComponent( "Message #$it", diff --git a/wear/wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md b/wear/wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md index 75c908d..55c5578 100644 --- a/wear/wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md +++ b/wear/wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md @@ -109,7 +109,8 @@ fun StatefulSwipeToDismissBox() { modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically), + verticalArrangement = + Arrangement.spacedBy(4.dp, Alignment.CenterVertically), ) { FilledTonalButton( onClick = { showMainScreen = false }, diff --git a/wear/wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md.txt b/wear/wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md.txt index 75c908d..55c5578 100644 --- a/wear/wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md.txt +++ b/wear/wear-compose-m3/references/material3/SwipeToDismissBoxSample.kt.md.txt @@ -109,7 +109,8 @@ fun StatefulSwipeToDismissBox() { modifier = Modifier.fillMaxSize().padding(horizontal = 8.dp, vertical = 8.dp), horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(4.dp, Alignment.CenterVertically), + verticalArrangement = + Arrangement.spacedBy(4.dp, Alignment.CenterVertically), ) { FilledTonalButton( onClick = { showMainScreen = false }, diff --git a/wear/wear-compose-m3/references/material3/SwipeToRevealSample.kt.md b/wear/wear-compose-m3/references/material3/SwipeToRevealSample.kt.md index faf8c70..253ce2b 100644 --- a/wear/wear-compose-m3/references/material3/SwipeToRevealSample.kt.md +++ b/wear/wear-compose-m3/references/material3/SwipeToRevealSample.kt.md @@ -70,7 +70,8 @@ fun SwipeToRevealSample() { text = { Text("Delete") }, ) }, - onSwipePrimaryAction = { /* This block is called when the full swipe gesture is performed. */ + onSwipePrimaryAction = { + /* This block is called when the full swipe gesture is performed. */ }, secondaryAction = { SecondaryActionButton( @@ -120,7 +121,8 @@ fun SwipeToRevealSingleActionCardSample() { modifier = Modifier.height(SwipeToRevealDefaults.LargeActionButtonHeight), ) }, - onSwipePrimaryAction = { /* This block is called when the full swipe gesture is performed. */ + onSwipePrimaryAction = { + /* This block is called when the full swipe gesture is performed. */ }, undoPrimaryAction = { UndoActionButton( @@ -279,7 +281,8 @@ fun SwipeToRevealWithScalingLazyColumnSample() { onSwipePrimaryAction = { messages.remove(message) }, secondaryAction = { SecondaryActionButton( - onClick = { /* This block is called when the secondary action is executed. */ + onClick = { + /* This block is called when the secondary action is executed. */ }, icon = { Icon(Icons.Outlined.MoreVert, contentDescription = "Options") }, ) diff --git a/wear/wear-compose-m3/references/material3/SwipeToRevealSample.kt.md.txt b/wear/wear-compose-m3/references/material3/SwipeToRevealSample.kt.md.txt index faf8c70..253ce2b 100644 --- a/wear/wear-compose-m3/references/material3/SwipeToRevealSample.kt.md.txt +++ b/wear/wear-compose-m3/references/material3/SwipeToRevealSample.kt.md.txt @@ -70,7 +70,8 @@ fun SwipeToRevealSample() { text = { Text("Delete") }, ) }, - onSwipePrimaryAction = { /* This block is called when the full swipe gesture is performed. */ + onSwipePrimaryAction = { + /* This block is called when the full swipe gesture is performed. */ }, secondaryAction = { SecondaryActionButton( @@ -120,7 +121,8 @@ fun SwipeToRevealSingleActionCardSample() { modifier = Modifier.height(SwipeToRevealDefaults.LargeActionButtonHeight), ) }, - onSwipePrimaryAction = { /* This block is called when the full swipe gesture is performed. */ + onSwipePrimaryAction = { + /* This block is called when the full swipe gesture is performed. */ }, undoPrimaryAction = { UndoActionButton( @@ -279,7 +281,8 @@ fun SwipeToRevealWithScalingLazyColumnSample() { onSwipePrimaryAction = { messages.remove(message) }, secondaryAction = { SecondaryActionButton( - onClick = { /* This block is called when the secondary action is executed. */ + onClick = { + /* This block is called when the secondary action is executed. */ }, icon = { Icon(Icons.Outlined.MoreVert, contentDescription = "Options") }, ) diff --git a/wear/wear-compose-m3/references/material3/SwitchButtonSample.kt.md b/wear/wear-compose-m3/references/material3/SwitchButtonSample.kt.md index 9e87918..11387fa 100644 --- a/wear/wear-compose-m3/references/material3/SwitchButtonSample.kt.md +++ b/wear/wear-compose-m3/references/material3/SwitchButtonSample.kt.md @@ -59,9 +59,7 @@ fun SplitSwitchButtonSample() { checked = checked, onCheckedChange = { checked = it }, toggleContentDescription = "Split Switch Button Sample", - onContainerClick = { - /* Do something */ - }, + onContainerClick = { /* Do something */ }, enabled = true, ) } diff --git a/wear/wear-compose-m3/references/material3/SwitchButtonSample.kt.md.txt b/wear/wear-compose-m3/references/material3/SwitchButtonSample.kt.md.txt index 9e87918..11387fa 100644 --- a/wear/wear-compose-m3/references/material3/SwitchButtonSample.kt.md.txt +++ b/wear/wear-compose-m3/references/material3/SwitchButtonSample.kt.md.txt @@ -59,9 +59,7 @@ fun SplitSwitchButtonSample() { checked = checked, onCheckedChange = { checked = it }, toggleContentDescription = "Split Switch Button Sample", - onContainerClick = { - /* Do something */ - }, + onContainerClick = { /* Do something */ }, enabled = true, ) } diff --git a/wear/wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md b/wear/wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md new file mode 100644 index 0000000..bfc840c --- /dev/null +++ b/wear/wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md @@ -0,0 +1,205 @@ +``` +/* + * Copyright 2025 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 + * + * http://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. + */ + +package androidx.wear.compose.navigation3.samples + +import androidx.annotation.Sampled +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.navigation3.runtime.NavKey +import androidx.navigation3.runtime.entryProvider +import androidx.navigation3.runtime.rememberNavBackStack +import androidx.navigation3.ui.NavDisplay +import androidx.wear.compose.foundation.lazy.TransformingLazyColumn +import androidx.wear.compose.foundation.lazy.items +import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState +import androidx.wear.compose.material3.Button +import androidx.wear.compose.material3.Card +import androidx.wear.compose.material3.EdgeButton +import androidx.wear.compose.material3.ListHeader +import androidx.wear.compose.material3.ScreenScaffold +import androidx.wear.compose.material3.SurfaceTransformation +import androidx.wear.compose.material3.Text +import androidx.wear.compose.material3.TitleCard +import androidx.wear.compose.material3.lazy.rememberTransformationSpec +import androidx.wear.compose.material3.lazy.transformedHeight +import androidx.wear.compose.navigation3.rememberSwipeDismissableSceneStrategy +import kotlinx.serialization.Serializable + +@Serializable object NotificationList : NavKey + +@Serializable data class NotificationDetail(val id: Int) : NavKey + +@Serializable object First : NavKey + +@Serializable object Second : NavKey + +data class NotificationItem(val id: Int, val title: String, val body: String) + +@Sampled +@Composable +fun ListDetailNavDisplaySample(onExit: () -> Unit = {}) { + // Example of using a NavDisplay with SwipeDismissableSceneStrategy for list-detail navigation. + + // Strongly-typed, serializable navigation destinations are defined at global scope as follows: + // @Serializable object NotificationList : NavKey + // @Serializable data class NotificationDetail(val id: Int) : NavKey + + // NotificationItem needs to be defined at top-level or class-level to ensure stability in + // Compose: + // data class NotificationItem(val id: Int, val title: String, val body: String) + val backStack = rememberNavBackStack(NotificationList) + + val notifications = remember { + listOf( + NotificationItem( + 0, + "☕ Coffee Break? Grab a pick-me-up", + "Step away from the screen and grab a pick-me-up. Step away from the screen and grab a pick-me-up.", + ), + NotificationItem( + 1, + "🌟 You're Awesome!", + "Just a little reminder in case you forgot 😊", + ), + NotificationItem( + 2, + "👀 Did you know our latest feature?", + "Check out [app name]'s latest feature update.", + ), + NotificationItem( + 3, + "📅 Appointment Time In 15 Minutes", + "Your meeting with [name] is in 15 minutes.", + ), + ) + } + + NavDisplay( + backStack = backStack, + sceneStrategies = listOf(rememberSwipeDismissableSceneStrategy()), + entryProvider = + entryProvider { + entry { + val state = rememberTransformingLazyColumnState() + val transformationSpec = rememberTransformationSpec() + ScreenScaffold( + state, + edgeButton = { EdgeButton(onClick = onExit) { Text("Exit") } }, + ) { contentPadding -> + TransformingLazyColumn(state = state, contentPadding = contentPadding) { + item { + ListHeader( + transformation = SurfaceTransformation(transformationSpec), + modifier = + Modifier.transformedHeight(this, transformationSpec) + .animateItem(), + ) { + Text("Notifications") + } + } + items(notifications) { notification -> + Card( + onClick = { + backStack.add(NotificationDetail(notification.id)) + }, + transformation = SurfaceTransformation(transformationSpec), + modifier = + Modifier.fillMaxWidth() + .transformedHeight(this, transformationSpec) + .animateItem(), + ) { + Text(notification.title) + } + } + } + } + } + + entry { key -> + val item = requireNotNull(notifications.find { item -> item.id == key.id }) + ScreenScaffold { contentPadding -> + Box( + Modifier.fillMaxSize().padding(contentPadding), + contentAlignment = Alignment.Center, + ) { + TitleCard(title = { Text(item.title) }, content = { Text(item.body) }) + } + } + } + }, + ) +} + +@Sampled +@Composable +fun NavDisplayWithOnBackBehaviorSample() { + // Example of using a NavDisplay with SwipeDismissableSceneStrategy and on back behavior. + + // Strongly-typed, serializable navigation destinations are defined at global scope as follows: + // @Serializable object First: NavKey + // @Serializable object Second: NavKey + val backStack = rememberNavBackStack(First) + + var swipedBackCount by remember { mutableIntStateOf(0) } + + NavDisplay( + backStack = backStack, + onBack = { + swipedBackCount++ + backStack.removeLastOrNull() + }, + sceneStrategies = listOf(rememberSwipeDismissableSceneStrategy()), + entryProvider = + entryProvider { + entry { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Text("First") + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = { backStack.add(Second) }) { Text("Second") } + + Spacer(modifier = Modifier.height(16.dp)) + Text("Swiped back $swipedBackCount times") + } + } + entry { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text("Second") + } + } + }, + ) +} +``` \ No newline at end of file diff --git a/wear/wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt b/wear/wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt new file mode 100644 index 0000000..bfc840c --- /dev/null +++ b/wear/wear-compose-m3/references/navigation3/SwipeDismissableSceneStrategySample.kt.md.txt @@ -0,0 +1,205 @@ +``` +/* + * Copyright 2025 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 + * + * http://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. + */ + +package androidx.wear.compose.navigation3.samples + +import androidx.annotation.Sampled +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.navigation3.runtime.NavKey +import androidx.navigation3.runtime.entryProvider +import androidx.navigation3.runtime.rememberNavBackStack +import androidx.navigation3.ui.NavDisplay +import androidx.wear.compose.foundation.lazy.TransformingLazyColumn +import androidx.wear.compose.foundation.lazy.items +import androidx.wear.compose.foundation.lazy.rememberTransformingLazyColumnState +import androidx.wear.compose.material3.Button +import androidx.wear.compose.material3.Card +import androidx.wear.compose.material3.EdgeButton +import androidx.wear.compose.material3.ListHeader +import androidx.wear.compose.material3.ScreenScaffold +import androidx.wear.compose.material3.SurfaceTransformation +import androidx.wear.compose.material3.Text +import androidx.wear.compose.material3.TitleCard +import androidx.wear.compose.material3.lazy.rememberTransformationSpec +import androidx.wear.compose.material3.lazy.transformedHeight +import androidx.wear.compose.navigation3.rememberSwipeDismissableSceneStrategy +import kotlinx.serialization.Serializable + +@Serializable object NotificationList : NavKey + +@Serializable data class NotificationDetail(val id: Int) : NavKey + +@Serializable object First : NavKey + +@Serializable object Second : NavKey + +data class NotificationItem(val id: Int, val title: String, val body: String) + +@Sampled +@Composable +fun ListDetailNavDisplaySample(onExit: () -> Unit = {}) { + // Example of using a NavDisplay with SwipeDismissableSceneStrategy for list-detail navigation. + + // Strongly-typed, serializable navigation destinations are defined at global scope as follows: + // @Serializable object NotificationList : NavKey + // @Serializable data class NotificationDetail(val id: Int) : NavKey + + // NotificationItem needs to be defined at top-level or class-level to ensure stability in + // Compose: + // data class NotificationItem(val id: Int, val title: String, val body: String) + val backStack = rememberNavBackStack(NotificationList) + + val notifications = remember { + listOf( + NotificationItem( + 0, + "☕ Coffee Break? Grab a pick-me-up", + "Step away from the screen and grab a pick-me-up. Step away from the screen and grab a pick-me-up.", + ), + NotificationItem( + 1, + "🌟 You're Awesome!", + "Just a little reminder in case you forgot 😊", + ), + NotificationItem( + 2, + "👀 Did you know our latest feature?", + "Check out [app name]'s latest feature update.", + ), + NotificationItem( + 3, + "📅 Appointment Time In 15 Minutes", + "Your meeting with [name] is in 15 minutes.", + ), + ) + } + + NavDisplay( + backStack = backStack, + sceneStrategies = listOf(rememberSwipeDismissableSceneStrategy()), + entryProvider = + entryProvider { + entry { + val state = rememberTransformingLazyColumnState() + val transformationSpec = rememberTransformationSpec() + ScreenScaffold( + state, + edgeButton = { EdgeButton(onClick = onExit) { Text("Exit") } }, + ) { contentPadding -> + TransformingLazyColumn(state = state, contentPadding = contentPadding) { + item { + ListHeader( + transformation = SurfaceTransformation(transformationSpec), + modifier = + Modifier.transformedHeight(this, transformationSpec) + .animateItem(), + ) { + Text("Notifications") + } + } + items(notifications) { notification -> + Card( + onClick = { + backStack.add(NotificationDetail(notification.id)) + }, + transformation = SurfaceTransformation(transformationSpec), + modifier = + Modifier.fillMaxWidth() + .transformedHeight(this, transformationSpec) + .animateItem(), + ) { + Text(notification.title) + } + } + } + } + } + + entry { key -> + val item = requireNotNull(notifications.find { item -> item.id == key.id }) + ScreenScaffold { contentPadding -> + Box( + Modifier.fillMaxSize().padding(contentPadding), + contentAlignment = Alignment.Center, + ) { + TitleCard(title = { Text(item.title) }, content = { Text(item.body) }) + } + } + } + }, + ) +} + +@Sampled +@Composable +fun NavDisplayWithOnBackBehaviorSample() { + // Example of using a NavDisplay with SwipeDismissableSceneStrategy and on back behavior. + + // Strongly-typed, serializable navigation destinations are defined at global scope as follows: + // @Serializable object First: NavKey + // @Serializable object Second: NavKey + val backStack = rememberNavBackStack(First) + + var swipedBackCount by remember { mutableIntStateOf(0) } + + NavDisplay( + backStack = backStack, + onBack = { + swipedBackCount++ + backStack.removeLastOrNull() + }, + sceneStrategies = listOf(rememberSwipeDismissableSceneStrategy()), + entryProvider = + entryProvider { + entry { + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + Text("First") + Spacer(modifier = Modifier.height(16.dp)) + Button(onClick = { backStack.add(Second) }) { Text("Second") } + + Spacer(modifier = Modifier.height(16.dp)) + Text("Swiped back $swipedBackCount times") + } + } + entry { + Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { + Text("Second") + } + } + }, + ) +} +``` \ No newline at end of file diff --git a/xr/display-glasses-with-jetpack-compose-glimmer/SKILL.md b/xr/display-glasses-with-jetpack-compose-glimmer/SKILL.md index b26e37d..ea03f71 100644 --- a/xr/display-glasses-with-jetpack-compose-glimmer/SKILL.md +++ b/xr/display-glasses-with-jetpack-compose-glimmer/SKILL.md @@ -9,7 +9,7 @@ description: Provides guidelines for developing projected Android XR apps for di license: Complete terms in LICENSE.txt metadata: author: Google LLC - last-updated: '2026-09-02' + last-updated: '2026-09-08' keywords: - Jetpack Compose Glimmer - audio glasses diff --git a/xr/display-glasses-with-jetpack-compose-glimmer/references/projectedcontext-source.md b/xr/display-glasses-with-jetpack-compose-glimmer/references/projectedcontext-source.md index 8eba114..bb03e93 100644 --- a/xr/display-glasses-with-jetpack-compose-glimmer/references/projectedcontext-source.md +++ b/xr/display-glasses-with-jetpack-compose-glimmer/references/projectedcontext-source.md @@ -160,68 +160,66 @@ public object ProjectedContext { ): Flow { val hostContext = createHostDeviceContext(context) return callbackFlow { - @OptIn(ExperimentalStdlibApi::class) - val coroutineDispatcher = - coroutineContext[CoroutineDispatcher] - ?: throw IllegalArgumentException( - "CoroutineContext must contain a CoroutineDispatcher." - ) - - fun checkAndSend() { - trySend(isProjectedDisplayAvailable(hostContext)) - } - - val virtualDeviceListener = - object : VirtualDeviceManager.VirtualDeviceListener { - override fun onVirtualDeviceCreated(deviceId: Int) { - checkAndSend() - } + @OptIn(ExperimentalStdlibApi::class) + val coroutineDispatcher = + coroutineContext[CoroutineDispatcher] + ?: throw IllegalArgumentException( + "CoroutineContext must contain a CoroutineDispatcher." + ) + + fun checkAndSend() { + trySend(isProjectedDisplayAvailable(hostContext)) + } - override fun onVirtualDeviceClosed(deviceId: Int) { - checkAndSend() - } + val virtualDeviceListener = + object : VirtualDeviceManager.VirtualDeviceListener { + override fun onVirtualDeviceCreated(deviceId: Int) { + checkAndSend() } - val displayListener = - object : DisplayManager.DisplayListener { - override fun onDisplayAdded(displayId: Int) { - checkAndSend() - } + override fun onVirtualDeviceClosed(deviceId: Int) { + checkAndSend() + } + } - override fun onDisplayChanged(displayId: Int) { - checkAndSend() - } + val displayListener = + object : DisplayManager.DisplayListener { + override fun onDisplayAdded(displayId: Int) { + checkAndSend() + } - override fun onDisplayRemoved(displayId: Int) { - checkAndSend() - } + override fun onDisplayChanged(displayId: Int) { + checkAndSend() } - checkAndSend() - - val virtualDeviceManager = - hostContext.getSystemService(VirtualDeviceManager::class.java) - virtualDeviceManager.registerVirtualDeviceListener( - coroutineDispatcher.asExecutor(), - virtualDeviceListener, - ) - - val displayManager = hostContext.getSystemService(DisplayManager::class.java) - val eventFilter = - EVENT_TYPE_DISPLAY_ADDED or - EVENT_TYPE_DISPLAY_CHANGED or - EVENT_TYPE_DISPLAY_REMOVED - displayManager.registerDisplayListener( - coroutineDispatcher.asExecutor(), - eventFilter, - displayListener, - ) - - awaitClose { - virtualDeviceManager.unregisterVirtualDeviceListener(virtualDeviceListener) - displayManager.unregisterDisplayListener(displayListener) + override fun onDisplayRemoved(displayId: Int) { + checkAndSend() + } } + + checkAndSend() + + val virtualDeviceManager = + hostContext.getSystemService(VirtualDeviceManager::class.java) + virtualDeviceManager.registerVirtualDeviceListener( + coroutineDispatcher.asExecutor(), + virtualDeviceListener, + ) + + val displayManager = hostContext.getSystemService(DisplayManager::class.java) + val eventFilter = + EVENT_TYPE_DISPLAY_ADDED or EVENT_TYPE_DISPLAY_CHANGED or EVENT_TYPE_DISPLAY_REMOVED + displayManager.registerDisplayListener( + coroutineDispatcher.asExecutor(), + eventFilter, + displayListener, + ) + + awaitClose { + virtualDeviceManager.unregisterVirtualDeviceListener(virtualDeviceListener) + displayManager.unregisterDisplayListener(displayListener) } + } .distinctUntilChanged() } diff --git a/xr/display-glasses-with-jetpack-compose-glimmer/references/stack-source.md b/xr/display-glasses-with-jetpack-compose-glimmer/references/stack-source.md index 925a5cd..6d7fb69 100644 --- a/xr/display-glasses-with-jetpack-compose-glimmer/references/stack-source.md +++ b/xr/display-glasses-with-jetpack-compose-glimmer/references/stack-source.md @@ -154,13 +154,12 @@ private fun StackItemLayout( ) { measurables, constraints -> var maxWidth = 0 var maxHeight = 0 - val placeables = - measurables.fastMap { - it.measure(constraints).also { placeable -> - maxWidth = maxOf(maxWidth, placeable.width) - maxHeight = maxOf(maxHeight, placeable.height) - } + val placeables = measurables.fastMap { + it.measure(constraints).also { placeable -> + maxWidth = maxOf(maxWidth, placeable.width) + maxHeight = maxOf(maxHeight, placeable.height) } + } if (!isLookingAhead) { state.layoutInfoInternal.updateMeasuredHeight(index = page, height = maxHeight) diff --git a/xr/display-glasses-with-jetpack-compose-glimmer/references/surface-source.md b/xr/display-glasses-with-jetpack-compose-glimmer/references/surface-source.md index 4e2e19c..b9876b1 100644 --- a/xr/display-glasses-with-jetpack-compose-glimmer/references/surface-source.md +++ b/xr/display-glasses-with-jetpack-compose-glimmer/references/surface-source.md @@ -568,11 +568,11 @@ private class SurfaceNode( val borderLayerProvider = borderLayerProvider ?: { - borderLayer - ?: requireGraphicsContext().createGraphicsLayer().also { - borderLayer = it - } - } + borderLayer + ?: requireGraphicsContext().createGraphicsLayer().also { + borderLayer = it + } + } .also { borderLayerProvider = it } val borderColor = lerp(DefaultSolidBorderIdleColor, focusedBorderColor1, focusProgress) @@ -723,11 +723,11 @@ private class SurfaceNode( val borderLayerProvider = borderLayerProvider ?: { - borderLayer - ?: requireGraphicsContext().createGraphicsLayer().also { - borderLayer = it - } - } + borderLayer + ?: requireGraphicsContext().createGraphicsLayer().also { + borderLayer = it + } + } .also { borderLayerProvider = it } borderLogic.drawBorder( this,