A subclassed NavigationPage bringing custom animated transitions and page lifecycle events.
To use for implementing custom navigation scenarios.
Android, iOS, MacCatalist, Windows, .net9 .net10.
- Easy to use - A subclassed NavigationPage acting as a drop-in replacement to navigate among pages and modals
- Smooth Transitions - Platform-native animations (Fade, Zoom, Whirl, Slide, Parallax, etc.)
- Transition Customization - Control animation speed and easing per page
- Lifecycle Callbacks - Pages now "know" when they are covered/removed/went on top for managing data and resources
- Queue-Based Navigation - Prevents concurrent navigation operations issues
- Zero Dependencies - No third-party libraries required
- Animations fixes for animations consistency across platforms.
- .NET 10 support thanks to yurkinh for the kick.
windows.mp4
dotnet add package Plugin.Maui.LightNavigationInstall-Package Plugin.Maui.LightNavigationIn your MauiProgram.cs, add the UseLightNavigation() call:
using LightNavigation;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseLightNavigation() // ← Add this line
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
});
return builder.Build();
}
}Replace your NavigationPage with LightNavigationPage:
using LightNavigation;
public partial class App : Application
{
public App()
{
InitializeComponent();
// Replace: MainPage = new NavigationPage(new MainPage());
// With:
MainPage = new LightNavigationPage(new MainPage());
}
}or when using FlyoutPage:
Detail = new LightNavigationPage(new MainPage());
_navigationRoot = Detail as NavigableElement; //<-- use this for navigationYou can find an example app in the LightNavigation.TestApp project included in this repository. Useful for testing and exploring features.
LightNavigationPage works exactly like the standard NavigationPage in fact it's a subclassed one:
// Push a page
await Navigation.PushAsync(new DetailPage());
// Pop a page
await Navigation.PopAsync();
// Pop to root
await Navigation.PopToRootAsync();
// Push modal
await Navigation.PushModalAsync(new NavigationPage(new LoginPage()));
// Pop modal
await Navigation.PopModalAsync();
// With animation control
await Navigation.PushAsync(new DetailPage(), animated: true);all methods have optional bool animated parameter!
Configure navigation behavior globally or per-page using static methods.
| Method | Description |
|---|---|
SetDefaultTransition(AnimationType transition) |
Sets the default transition animation type to use when a page doesn't have a specific transition set. |
SetDefaultTransitionSpeedMs(int msIn, int msOut) |
Sets global default transition speeds in milliseconds for push (in) and pop (out). |
| Method | Description |
|---|---|
SetTransition(BindableObject page, AnimationType type) |
Sets the transition animation type for the specified page. |
SetTransitionSpeedMs(BindableObject page, int duration) |
Sets the transition speed (duration in ms) for the specified page. 0 = default. |
SetTransitionEasing(BindableObject page, TransitionEasing easing) |
Sets the transition easing type for the specified page. |
| Method | Description |
|---|---|
GetTransition(BindableObject page) |
Gets the transition animation type for the specified page. |
GetTransitionSpeedMs(BindableObject page) |
Gets the transition speed for the specified page. |
GetTransitionEasing(BindableObject page) |
Gets the transition easing type for the specified page. |
| Method | Description |
|---|---|
GetDefaultTransition() |
Gets the current global default transition animation type. |
GetDefaultTransitionSpeedInMs() |
Gets the global default push/in animation duration in ms. |
GetDefaultTransitionSpeedOutMs() |
Gets the global default pop/out animation duration in ms. |
Example:
//inside MauiProgram.cs
LightNavigationPage.SetDefaultTransition(AnimationType.SlideFromBottom);
LightNavigationPage.SetDefaultTransitionSpeedMs(300, 200);Implement INavigationAware on your pages to receive navigation lifecycle callbacks.
| Method | Description |
|---|---|
OnPushing() |
Called just before this page is about to be pushed onto the navigation stack. |
OnTopmost() |
Called when this page becomes the topmost page (visible to user). |
OnCovered() |
Called when this page is covered by another page (pushed on top of it). |
OnPopping() |
Called just before this page is about to be popped from the navigation stack. |
OnRemoved() |
Called when this page is removed from the navigation stack. |
Example implementation:
using LightNavigation;
using Microsoft.Maui.Controls;
public partial class MyPage : ContentPage, INavigationAware
{
public MyPage()
{
InitializeComponent();
}
// Called just before this page is pushed onto the navigation stack
public void OnPushing()
{
System.Diagnostics.Debug.WriteLine("Page is being pushed");
// can start preparing data etc..
}
// Called when this page becomes the topmost page (visible to user)
public void OnTopmost()
{
System.Diagnostics.Debug.WriteLine("Page is now topmost");
// Refresh data, resume animations, etc.
}
// Called when this page is covered by another page (pushed on top of it)
public void OnCovered()
{
System.Diagnostics.Debug.WriteLine("Page is being covered");
// Pause animations, etc.
}
// Called just before this page is popped from the navigation stack
public void OnPopping()
{
System.Diagnostics.Debug.WriteLine("Page is being popped");
}
// Called when this page is removed from the navigation stack
public void OnRemoved()
{
System.Diagnostics.Debug.WriteLine("Page has been removed");
// Clean up resources, unsubscribe from events, etc.
this.DisconnectHandlers(); // <-- important to avoid memory leaks
// Dispose other resources if needed
}
}LightNavigation supports 13 different transition animations that can be applied globally or per-page.
Available Transition Types:
Default- Platform native transitionNone- No animation (instant)SlideFromRight/SlideFromLeft/SlideFromBottom/SlideFromTopParallaxSlideFromRight/ParallaxSlideFromLeft- iOS-style parallax effectFade- Crossfade between pagesZoomIn/ZoomOut- Zoom from/to centerWhirlIn- Rotate + zoom with 180° rotationWhirlIn3- Rotate + zoom with 3 full rotations (1080°)
Note: All 13 custom transitions are fully implemented on Android, Windows, iOS, and Mac Catalyst.
Control animation speed and easing for individual pages using the attached properties or static methods (see below).
Available Easing Types:
Default- Platform default (Decelerate for push, Accelerate for pop)Linear- Constant speedDecelerate- Fast start, slow endAccelerate- Slow start, fast endAccelerateDecelerate- Slow-fast-slow
Note: Speed and easing customization is fully supported on all platforms (Android, Windows, iOS, and Mac Catalyst).
XAML Usage:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ln="clr-namespace:LightNavigation;assembly=LightNavigation"
x:Class="MyApp.DetailPage"
ln:LightNavigationPage.Transition="Fade"
ln:LightNavigationPage.TransitionSpeed="300"
ln:LightNavigationPage.TransitionEasing="Linear">
<!-- Page content -->
</ContentPage>- Uses
FrameLayoutdirectly (no fragments) - Custom view animations with
ViewPropertyAnimator - Sequential navigation queue to prevent concurrent operations
- Navigation Handling: Uses MAUI's
RequestNavigationcommand mapper
- Uses
UINavigationControllerwith custom view management UIViewPropertyAnimatorfor smooth, interruptible animations withCGAffineTransformfor complex transitions- Parallax effect and custom transitions for native iOS feel
- Navigation Handling: Uses event-based navigation (
INavigationPageControllerevents) for reliable operation- Subscribes to
PushRequested,PopRequested, andPopToRootRequestedevents - This approach ensures compatibility with iOS navigation lifecycle
- Subscribes to
- Uses
Gridcontainer for simplicity Storyboardanimations withDoubleAnimationandCompositeTransform- Dual-view rendering during transitions
- Navigation Handling: Uses MAUI's
RequestNavigationcommand mapper
- Push Animation: 150ms (Android/Windows), 300ms (iOS)
- Pop Animation: 100ms (Android), 150ms (Windows), 300ms (iOS)
- WhirlIn3 Animation: 400ms (all platforms) - Extended duration for dramatic 3-rotation effect
All durations can be overridden per-page using LightNavigationPage.SetTransitionSpeedMs().
All platforms implement a queue-based navigation system using:
Queue<Func<Task>>for navigation operationsSemaphoreSlimfor sequential processing- Prevents concurrent navigation that causes crashes
| Feature | Standard NavigationPage | LightNavigationPage |
|---|---|---|
| Black flash on transitions | ❌ Yes (Android/Windows) | ✅ No |
| Smooth animations | ✅ Platform-optimized | |
| Custom transition types | ❌ No | ✅ 13 built-in types |
| Animation speed control | ❌ No | ✅ Per-page customization |
| Easing customization | ❌ No | ✅ 5 easing types |
| Navigation queue | ❌ No | ✅ Yes |
| Lifecycle callbacks | ❌ Limited | ✅ Full INavigationAware |
| Concurrent navigation safety | ❌ Can crash | ✅ Protected |
MIT License - See LICENSE file for details
Contributions are welcome! Please feel free to submit a Pull Request.
If you encounter any issues or have questions:
- Check the documentation
- Review the included LightNavigation.TestApp for usage examples
- If an issue is reproducible inside LightNavigation.TestApp please open an issue on GitHub
Made with ❤️ for the .NET MAUI community