Skip to content

Commit bdf3530

Browse files
authored
Merge pull request #5 from AnnulusGames/renew-page-architecture
Renew page architecture
2 parents 270cdf6 + 9c763bc commit bdf3530

33 files changed

Lines changed: 402 additions & 875 deletions

README.md

Lines changed: 70 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -37,48 +37,40 @@ Alternatively, open Packages/manifest.json and add the following to the dependen
3737

3838
## Basic Concepts
3939

40-
In NavStack, a single screen is divided into units called "Pages." The only requirement for being a Page is implementing the `IPage` interface. You can represent a Page with any object, such as a GameObject, VisualElement, or Scene. (An implementation for uGUI is provided by default.)
40+
In NavStack, a screen is divided into units called "Pages." The only requirement for a Page is the implementation of the `IPage` interface, allowing any object such as GameObjects, VisualElements, or Scenes to be represented as a Page.
4141

42-
Page transitions and lifecycle management are handled by "Navigation." NavStack provides two types of Navigation: `INavigationStack`, which can stack Page transitions, and `INaviagtionSheet`, which only switches between active Pages without maintaining a history of transitions.
42+
Screen transitions and lifecycle management are handled by "Navigation." NavStack provides two types of Navigation: `INavigationStack`, which can stack Page transitions, and `INaviagtionSheet`, which switches between active Pages without keeping a history of transitions.
4343

4444
## Page Lifecycle
4545

46-
The basic interface for a Page, `IPage`, has the following definition. Each event associated with a Page is called by Navigation, allowing you to customize the screen transition process by implementing these methods.
46+
The `IPage` interface defines the basic events for a Page's lifecycle. Each event is called from the Navigation side, allowing customization of screen transition processes.
4747

4848
```cs
4949
public interface IPage
5050
{
51-
IList<IPageLifecycleEvent> LifecycleEvents { get; }
52-
53-
UniTask OnInitialize(CancellationToken cancellationToken = default);
54-
UniTask OnAppear(NavigationOptions options, CancellationToken cancellationToken = default);
55-
UniTask OnDisappear(NavigationOptions options, CancellationToken cancellationToken = default);
56-
UniTask OnCleanup(CancellationToken cancellationToken = default);
51+
UniTask OnNavigatedFrom(NavigationContext context, CancellationToken cancellationToken = default);
52+
UniTask OnNavigatedTo(NavigationContext context, CancellationToken cancellationToken = default);
5753
}
5854
```
5955

60-
| Event | Description |
61-
| - | - |
62-
| OnInitialize | Called once when the Page is initialized. |
63-
| OnAppear | Called each time the Page becomes visible. |
64-
| OnDisappear | Called each time the Page becomes hidden. |
65-
| OnCleanup | Called once when the Page is cleaned up. |
56+
| Event | Description |
57+
| --------------- | ------------------------------------------ |
58+
| OnNavigatedFrom | Called when navigating away from the Page. |
59+
| OnNavigatedTo | Called when navigating to the Page. |
6660

67-
Additionally, you can add callbacks before and after each lifecycle event by implementing objects that implement `IPageLifecycleEvent`.
61+
Additionally, by implementing `IPageLifecycleEvent`, you can add additional lifecycle events for the Page.
6862

6963
```cs
7064
public interface IPageLifecycleEvent
7165
{
72-
UniTask OnInitialize(CancellationToken cancellationToken = default);
73-
UniTask OnCleanup(CancellationToken cancellationToken = default);
74-
UniTask OnAppear(NavigationOptions options, CancellationToken cancellationToken = default);
75-
UniTask OnDisappear(NavigationOptions options, CancellationToken cancellationToken = default);
66+
UniTask OnAttached(CancellationToken cancellationToken = default);
67+
UniTask OnDetached(CancellationToken cancellationToken = default);
7668
}
7769
```
7870

7971
## NavigationStack
8072

81-
NavigationStack supports stacked screen transitions. When you push a Page onto the stack, it becomes the active Page, and the last Page pushed becomes the active Page. To push a Page, use `PushAsync()`, and to pop a Page, use `PopAsync()`.
73+
NavigationStack supports stacked screen transitions. Pages pushed onto the stack are stacked, and the last pushed Page becomes the active Page. You can push a Page using `PushAsync()` and pop using `PopAsync()`.
8274

8375
```cs
8476
INavigationStack navigationStack;
@@ -88,17 +80,21 @@ await navigationStack.PushAsync(page);
8880
await navigationStack.PopAsync();
8981
```
9082

91-
In NavigationStack, the Page lifecycle is handled as follows:
83+
You can also add NavigationStack-specific events to Pages by implementing `IPageStackEvent`.
9284

93-
1. `OnInitialize` is called when pushing a Page.
94-
2. During transitions, `OnDisappear` is called for the previous Page and `OnAppear` for the new Page.
95-
3. `OnCleanup` is called when popping a Page.
85+
```cs
86+
public interface IPageStackEvent
87+
{
88+
UniTask OnPush(NavigationContext context, CancellationToken cancellationToken = default);
89+
UniTask OnPop(NavigationContext context, CancellationToken cancellationToken = default);
90+
}
91+
```
9692

9793
## NavigationSheet
9894

99-
NavigationSheet supports tab-like switching between active Pages. Unlike NavigationStack, it does not maintain a history of Page transitions.
95+
NavigationSheet supports switching between active Pages, similar to tabs. Unlike NavigationStack, it does not keep a history of Page transitions.
10096

101-
To use NavigationSheet, you need to add Pages with `AddAsync()` beforehand.
97+
You need to use `AddAsync()` to add Pages to the NavigationSheet.
10298

10399
```cs
104100
INavigationSheet navigationSheet;
@@ -126,78 +122,88 @@ await navigationSheet.RemoveAsync(page3);
126122
await navigationSheet.RemoveAllAsync();
127123
```
128124

129-
In NavigationSheet, the Page lifecycle is handled as follows:
125+
## NavigationContext
130126

131-
1. `OnInitialize` is called when adding a Page.
132-
2. During transitions, `OnDisappear` is called for the previous Page and `OnAppear` for the new Page.
133-
3. `OnCleanup` is called when removing a Page.
127+
You can pass `NavigationContext` during Page transitions to pass data between Pages and specify transition options.
134128

135-
## NavigationOptions
129+
### Passing Data
136130

137-
When performing Page transitions using Navigation, you can pass `NavigationOptions`. If omitted, the options specified in the Navigation's `DefaultOptions` are applied.
131+
You can pass data to the destination Page through `NavigationContext`.
138132

139-
| Property | Description |
140-
| - | - |
141-
| Animated | Whether to play transition animations (default value is true) |
142-
| AwaitOpearion | Behavior when a transition operation is called again while a Page transition is in progress (default value is NavigationAwaitOperation.Error) |
133+
```cs
134+
var page = new ExamplePage();
143135

144-
## Navigation Callbacks
136+
var context = new NavigationContext()
137+
{
138+
Parameters = { { "id", "123456" } }
139+
};
145140

146-
By implementing `INavigationCallbackReceiver`, you can add callbacks before and after each Page lifecycle event by adding objects to Navigation.
141+
await navigationStack.PushAsync(page, context, cancellationToken);
147142

148-
```cs
149-
public interface INavigationCallbackReceiver
143+
class ExamplePage : IPage
150144
{
151-
void OnBeforeInitialize(IPage page) { }
152-
void OnAfterInitialize(IPage page) { }
153-
void OnBeforeCleanup(IPage page) { }
154-
void OnAfterCleanup(IPage page) { }
155-
void OnBeforeAppear(IPage page) { }
156-
void OnAfterAppear(IPage page) { }
157-
void OnBeforeDisappear(IPage page) { }
158-
void OnAfterDisappear(IPage page) { }
145+
public UniTask OnNavigatedFrom(NavigationContext context, CancellationToken cancellationToken = default)
146+
{
147+
var id = (string)context.Parameters["id"];
148+
149+
...
150+
}
151+
152+
...
159153
}
160154
```
161155

156+
### NavigationOptions
157+
158+
You can specify transition options using `NavigationOptions`.
159+
162160
```cs
163-
INavigationCallbackReceiver receiver;
164-
navigation.CallbackReveivers.Add(receiver);
161+
var context = new NavigationContext()
162+
{
163+
Options = new NavigationOptions()
164+
{
165+
Animated = true,
166+
AwaitOperation = NavigationAwaitOperation.Drop,
167+
}
168+
};
169+
170+
await navigationStack.PushAsync(page, context, cancellationToken);
165171
```
166172

167-
## Workflow for uGUI
173+
| Property | Description |
174+
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
175+
| Animated | Specifies whether to play transition animations (default is true). |
176+
| AwaitOperation | Specifies the behavior when a transition operation is called again during Page transition (default is NavigationAwaitOperation.Error). |
168177

169-
NavStack provides components for handling Pages and Navigation with uGUI by default.
178+
## Workflow for uGUI
170179

171180
When using NavStack with uGUI, add the `Navigation Stack` / `Navigation Sheet` component to any object placed under the Canvas.
172181

173-
<img src="https://github.com/AnnulusGames/NavStack/blob/main/docs/images/img-navigationstack-inspector.png" width="500">
174-
175-
Next, create Pages to display UI. Define a component that inherits from the `Page` class.
182+
Next, create Pages for displaying UI. Implement a component that inherits from `IPage`.
176183

177184
```cs
178-
public class SamplePage1 : Page
185+
public class SamplePage1 : MonoBehaviour, IPage
179186
{
180187
[SerializeField] CanvasGroup canvasGroup;
181188

182-
// Override methods to customize events
183-
protected override async UniTask OnAppearCore(NavigationOptions options, CancellationToken cancellationToken = default)
189+
public async UniTask OnNavigatedFrom(NavigationContext context, CancellationToken cancellationToken = default)
184190
{
185-
if (!options.Animated)
191+
if (!context.Options.Animated)
186192
{
187193
canvasGroup.alpha = 1f;
188194
return;
189195
}
190196

191-
// In this example, LitMotion is used to implement tween animations
197+
// Example implementation using LitMotion for tween animations
192198
await LMotion.Create(0f, 1f, 0.25f)
193199
.WithEase(Ease.InQuad)
194200
.BindToCanvasGroupAlpha(canvasGroup)
195201
.ToUniTask(CancellationTokenSource.CreateLinkedTokenSource(destroyCancellationToken, cancellationToken).Token);
196202
}
197203

198-
protected override async UniTask OnDisappearCore(NavigationOptions options, CancellationToken cancellationToken = default)
204+
public async UniTask OnNavigatedTo(NavigationContext context, CancellationToken cancellationToken = default)
199205
{
200-
if (!options.Animated)
206+
if (!context.Options.Animated)
201207
{
202208
canvasGroup.alpha = 0f;
203209
return;
@@ -211,7 +217,7 @@ public class SamplePage1 : Page
211217
}
212218
```
213219

214-
It's convenient to manage Prefabs of created Pages. Prefab-ized Pages can be added to Navigation using `PushNewObjectAsync()` or `AddNewObjectAsync()`, allowing for the generation/destruction of objects based on the Page lifecycle.
220+
Prefab the created Page objects for convenience. By adding Prefabed Pages using `PushNewObjectAsync()` or `AddNewObjectAsync()`, you can manage object generation/destruction based on the Page lifecycle.
215221

216222
```cs
217223
Page prefab;

0 commit comments

Comments
 (0)