Skip to content

Commit fe3d03d

Browse files
committed
feat: Add READMEs for all recipes
This commit adds a `README.md` file to each recipe package. Each README explains the purpose of the specific recipe and details how it works, providing context and documentation for the example code.
1 parent 0c7b01b commit fe3d03d

File tree

18 files changed

+270
-0
lines changed

18 files changed

+270
-0
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Animations Recipe
2+
3+
This recipe shows how to override the default animations at the `NavDisplay` level, and at the individual destination level.
4+
5+
## How it works
6+
7+
The `NavDisplay` composable takes `transitionSpec`, `popTransitionSpec`, and `predictivePopTransitionSpec` parameters to define the animations for forward, backward, and predictive back navigation respectively. These animations will be applied to all destinations by default.
8+
9+
In this example, we use `slideInHorizontally` and `slideOutHorizontally` to create a sliding animation for forward and backward navigation.
10+
11+
It is also possible to override these animations for a specific destination by providing a different `transitionSpec` and `popTransitionSpec` to the `entry` composable. In this recipe, `ScreenC` has a custom vertical slide animation.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Basic Recipe
2+
3+
This recipe shows a basic example of how to use the Navigation 3 API with two screens.
4+
5+
## How it works
6+
7+
This example defines two routes: `RouteA` and `RouteB`. `RouteA` is a `data object` representing a simple screen, while `RouteB` is a `data class` that takes an `id` as a parameter.
8+
9+
A `mutableStateListOf<Any>` is used to manage the navigation back stack.
10+
11+
The `NavDisplay` composable is used to display the current screen. Its `entryProvider` parameter is a lambda that takes a route from the back stack and returns a `NavEntry`. Inside the `entryProvider`, a `when` statement is used to determine which composable to display based on the route.
12+
13+
To navigate from `RouteA` to `RouteB`, we simply add a `RouteB` instance to the back stack. The `id` is passed as an argument to the `RouteB` data class.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Basic DSL Recipe
2+
3+
This recipe shows a basic example of how to use the Navigation 3 API with two screens, using the `entryProvider` DSL and a persistent back stack.
4+
5+
## How it works
6+
7+
This example is similar to the basic recipe, but with a few key differences:
8+
9+
1. **Persistent Back Stack**: It uses `rememberNavBackStack(RouteA)` to create and remember the back stack. This makes the back stack persistent across configuration changes (e.g., screen rotation). To use `rememberNavBackStack`, the navigation keys must be serializable, which is why `RouteA` and `RouteB` are annotated with `@Serializable` and implement the `NavKey` interface.
10+
11+
2. **`entryProvider` DSL**: Instead of a `when` statement, this example uses the `entryProvider` DSL to define the content for each route. The `entry<RouteType>` function is used to associate a route type with its composable content.
12+
13+
The navigation logic remains the same: to navigate from `RouteA` to `RouteB`, we add a `RouteB` instance to the back stack.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Basic Saveable Recipe
2+
3+
This recipe shows a basic example of how to create a persistent back stack that survives configuration changes.
4+
5+
## How it works
6+
7+
To make the back stack persistent, we use the `rememberNavBackStack` function. This function creates and remembers the back stack across configuration changes (e.g., screen rotation).
8+
9+
A requirement for using `rememberNavBackStack` is that the navigation keys (routes) must be serializable. In this example, `RouteA` and `RouteB` are annotated with `@Serializable` and implement the `NavKey` interface.
10+
11+
This example uses a `when` statement within the `entryProvider` to map routes to their corresponding composables, but it could also be used with the `entryProvider` DSL.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Bottom Sheet Recipe
2+
3+
This recipe demonstrates how to display a destination as a modal bottom sheet.
4+
5+
## How it works
6+
7+
To show a destination as a bottom sheet, you need to do two things:
8+
9+
1. **Use `BottomSheetSceneStrategy`**: Create an instance of `BottomSheetSceneStrategy` and pass it to the `sceneStrategy` parameter of the `NavDisplay` composable.
10+
11+
2. **Add metadata to the destination**: For the destination that you want to display as a bottom sheet, add `BottomSheetSceneStrategy.bottomSheet()` to its metadata. This is done in the `entry` function.
12+
13+
In this example, `RouteB` is configured to be a bottom sheet. When you navigate from `RouteA` to `RouteB`, `RouteB` will be displayed in a modal bottom sheet that slides up from the bottom of the screen.
14+
15+
The content of the bottom sheet can be styled as needed. In this recipe, the content is clipped to have rounded corners.
16+
17+
For more information, see the official documentation on [custom layouts](https://developer.android.com/guide/navigation/navigation-3/custom-layouts).
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Common UI Recipe
2+
3+
This recipe demonstrates how to implement a common navigation UI pattern with a bottom navigation bar and multiple back stacks, where each tab in the navigation bar has its own navigation history.
4+
5+
## How it works
6+
7+
This example has three top-level destinations: Home, ChatList, and Camera. The ChatList destination also has a sub-route, ChatDetail.
8+
9+
### `TopLevelBackStack`
10+
11+
The core of this recipe is the `TopLevelBackStack` class, which is responsible for managing the navigation state. It works as follows:
12+
13+
- It maintains a separate back stack for each top-level destination (tab).
14+
- It keeps track of the currently selected top-level destination.
15+
- It provides a single, flattened back stack that can be used by the `NavDisplay` composable. This flattened back stack is a combination of the individual back stacks of all the tabs.
16+
17+
### UI Structure
18+
19+
The UI is built using a `Scaffold` composable, with a `NavigationBar` as the `bottomBar`.
20+
21+
- The `NavigationBar` displays an item for each top-level destination. When an item is clicked, it calls `topLevelBackStack.addTopLevel` to switch to the corresponding tab, preserving the navigation history of each tab.
22+
- The `NavDisplay` composable is placed in the content area of the `Scaffold`. It is responsible for displaying the current screen based on the flattened back stack provided by `TopLevelBackStack`.
23+
24+
This approach allows for a common navigation pattern where users can switch between different sections of the app, and each section maintains its own navigation history.
25+
26+
### State Preservation
27+
28+
It's important to note how the navigation state is managed in this recipe. When a user navigates away from a top-level destination (e.g., by pressing the back button until they return to a previous tab), the entire navigation history for that destination is cleared. The state is not saved. When the user returns to that tab later, they will start from its initial screen.
29+
30+
**Note**: In this example, the Home route can move above the ChatList and Camera routes, meaning navigating back from Home doesn't necessarily leave the app. The app will exit when the user goes back from a single remaining top level route in the back stack.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Conditional Navigation Recipe
2+
3+
This recipe demonstrates how to implement conditional navigation, where certain destinations are only accessible if a condition is met (in this case, if the user is logged in).
4+
5+
## How it works
6+
7+
This example has a `Profile` destination that requires the user to be logged in. If the user is not logged in and attempts to navigate to `Profile`, they are redirected to a `Login` screen. After a successful login, they are automatically navigated to the `Profile` screen.
8+
9+
### `AppBackStack`
10+
11+
The core of this recipe is the custom `AppBackStack` class, which encapsulates the logic for conditional navigation.
12+
13+
- **`RequiresLogin` interface**: A marker interface, `RequiresLogin`, is used to identify destinations that require the user to be logged in. The `Profile` destination implements this interface.
14+
15+
- **Redirecting to Login**: When the `add` function is called with a destination that implements `RequiresLogin` and the user is not logged in, `AppBackStack` stores the intended destination and adds the `Login` route to the back stack instead.
16+
17+
- **Handling Login**: When the `login` function is called, it sets the user's status to logged in. If there is a stored destination that the user was trying to access, it adds that destination to the back stack and removes the `Login` screen.
18+
19+
- **Handling Logout**: When the `logout` function is called, it sets the user's status to logged out and removes any destinations from the back stack that require the user to be logged in.
20+
21+
This approach provides a clean way to handle conditional navigation by centralizing the logic in a custom back stack implementation.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Dialog Recipe
2+
3+
This recipe demonstrates how to display a destination as a dialog.
4+
5+
## How it works
6+
7+
To show a destination as a dialog, you need to do two things:
8+
9+
1. **Use `DialogSceneStrategy`**: Create an instance of `DialogSceneStrategy` and pass it to the `sceneStrategy` parameter of the `NavDisplay` composable.
10+
11+
2. **Add metadata to the destination**: For the destination that you want to display as a dialog, add `DialogSceneStrategy.dialog()` to its metadata. This is done in the `entry` function. You can also pass a `DialogProperties` object to customize the dialog's behavior and appearance.
12+
13+
In this example, `RouteB` is configured to be a dialog. When you navigate from `RouteA` to `RouteB`, `RouteB` will be displayed in a dialog window.
14+
15+
The content of the dialog can be styled as needed. In this recipe, the content is clipped to have rounded corners.
16+
17+
For more information, see the official documentation on [custom layouts](https://developer.android.com/guide/navigation/navigation-3/custom-layouts).
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# Material List-Detail Recipe
2+
3+
This recipe demonstrates how to create an adaptive list-detail layout using the `ListDetailSceneStrategy` from the Material 3 Adaptive library. This layout automatically adjusts to show one, two, or three panes depending on the available screen width.
4+
5+
## How it works
6+
7+
This example has three destinations: `ConversationList`, `ConversationDetail`, and `Profile`.
8+
9+
### `ListDetailSceneStrategy`
10+
11+
The key to this recipe is the `rememberListDetailSceneStrategy`, which provides the logic for the adaptive layout.
12+
13+
- **Pane Roles**: Each destination is assigned a role using metadata:
14+
- `ListDetailSceneStrategy.listPane()`: For the primary (list) content. This pane is always visible. A placeholder can be provided to be shown in the detail pane area when no detail content is selected.
15+
- `ListDetailSceneStrategy.detailPane()`: For the secondary (detail) content.
16+
- `ListDetailSceneStrategy.extraPane()`: For tertiary content.
17+
18+
- **Adaptive Layout**: The `ListDetailSceneStrategy` automatically handles the layout. On smaller screens, only one pane is shown at a time. On wider screens, it will show the list and detail panes side-by-side. On very wide screens, it can show all three panes: list, detail, and extra.
19+
20+
- **Navigation**: Navigation between the panes is handled by adding and removing destinations from the back stack as usual. The `ListDetailSceneStrategy` observes the back stack and adjusts the layout accordingly.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Material Supporting Pane Recipe
2+
3+
This recipe demonstrates how to create an adaptive layout with a main pane and a supporting pane using the `SupportingPaneSceneStrategy` from the Material 3 Adaptive library. This layout is useful for displaying supplementary content alongside the main content on larger screens.
4+
5+
## How it works
6+
7+
This example has three destinations: `MainVideo`, `RelatedVideos`, and `Profile`.
8+
9+
### `SupportingPaneSceneStrategy`
10+
11+
The `rememberSupportingPaneSceneStrategy` provides the logic for this adaptive layout.
12+
13+
- **Pane Roles**: Each destination is assigned a role using metadata:
14+
- `SupportingPaneSceneStrategy.mainPane()`: For the primary content. This pane is always visible.
15+
- `SupportingPaneSceneStrategy.supportingPane()`: For the supplementary content. This pane is shown alongside the main pane on larger screens.
16+
- `SupportingPaneSceneStrategy.extraPane()`: For tertiary content that can be displayed alongside the supporting pane on even larger screens.
17+
18+
- **Adaptive Layout**: The `SupportingPaneSceneStrategy` automatically handles the layout. On smaller screens, only the main pane is shown. On larger screens, the supporting pane is shown next to the main pane.
19+
20+
- **Back Navigation**: The `BackNavigationBehavior` is customized in this example to `PopUntilCurrentDestinationChange`. This means that when the user presses the back button, the supporting pane will be dismissed, revealing the main pane underneath.
21+
22+
- **Navigation**: Navigation is handled by adding and removing destinations from the back stack. The `SupportingPaneSceneStrategy` observes these changes and adjusts the layout accordingly.

0 commit comments

Comments
 (0)