.NET MAUI页面导航动画如何实现从左到右的反向转场?
MAUI页面转场:实现从左到右的前进导航动画
默认情况下,调用GoToAsync并传入true参数会触发从右到左的前进转场动画,若要改为从左到右,可通过以下两种实用技巧实现:
方法一:手动控制导航动画(跨平台通用)
通过拦截默认导航逻辑,手动添加自定义动画实现方向反转:
- 在
AppShell中注册Navigating事件并注册目标页面路由:
public AppShell() { InitializeComponent(); Navigating += AppShell_Navigating; Routing.RegisterRoute(nameof(DashboardPage), typeof(DashboardPage)); }
- 实现事件处理逻辑,自定义转场动画:
private async void AppShell_Navigating(object sender, ShellNavigatingEventArgs e) { // 仅处理前进到目标页面的导航,排除返回操作 if (e.Source != ShellNavigationSource.Pop && e.Target.Location.OriginalString.Contains(nameof(DashboardPage))) { e.Cancel(); // 取消默认导航动画 var currentPage = Shell.Current.CurrentPage; var targetPage = (Page)Activator.CreateInstance(typeof(DashboardPage)); // 设置目标页面初始位置在屏幕左侧外 targetPage.TranslationX = -DeviceDisplay.MainDisplayInfo.Width; // 推入目标页面 await Shell.Current.Navigation.PushAsync(targetPage); // 执行从左到右的转场动画:目标页面滑入,当前页面滑出到右侧 await Task.WhenAll( targetPage.TranslateTo(0, 0, 250, Easing.CubicInOut), currentPage.TranslateTo(DeviceDisplay.MainDisplayInfo.Width, 0, 250, Easing.CubicInOut) ); // 重置当前页面位置,避免后续导航异常 currentPage.TranslationX = 0; } }
方法二:平台特定自定义(贴近原生效果)
如果需要更贴合系统原生的动画表现,可针对Android和iOS分别配置:
Android端
- 在Android项目的
Resources/anim目录下创建两个动画文件:slide_in_left.xml(新页面从左滑入):
<set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="-100%" android:toXDelta="0%" android:duration="250"/> </set>
slide_out_right.xml(当前页面滑出到右侧):
<set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:fromXDelta="0%" android:toXDelta="100%" android:duration="250"/> </set>
- 在
MainActivity的OnCreate方法中替换默认导航动画:
protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); Shell.SetNavigationTransition(this, new Android.ShellNavigationTransition { EnterResource = Resource.Animation.slide_in_left, ExitResource = Resource.Animation.slide_out_right }); }
iOS端
- 在
AppDelegate中修改导航控制器的转场代理:
public override bool FinishedLaunching(UIApplication app, NSDictionary options) { global::Xamarin.Forms.Forms.Init(); LoadApplication(new App()); var navController = (UINavigationController)Window.RootViewController; navController.Delegate = new CustomNavigationDelegate(); return base.FinishedLaunching(app, options); } public class CustomNavigationDelegate : UINavigationControllerDelegate { public override IUIViewControllerAnimatedTransitioning GetAnimationControllerForOperation(UINavigationControllerOperation operation, UIViewController fromVC, UIViewController toVC) { if (operation == UINavigationControllerOperation.Push) { return new LeftToRightTransitionAnimator(); } return base.GetAnimationControllerForOperation(operation, fromVC, toVC); } } public class LeftToRightTransitionAnimator : UIViewControllerAnimatedTransitioning { public double TransitionDuration(IUIViewControllerContextTransitioning transitionContext) => 0.25; public void AnimateTransition(IUIViewControllerContextTransitioning transitionContext) { var fromVC = transitionContext.GetViewControllerForKey(UITransitionContext.FromViewControllerKey); var toVC = transitionContext.GetViewControllerForKey(UITransitionContext.ToViewControllerKey); var containerView = transitionContext.ContainerView; containerView.AddSubview(toVC.View); toVC.View.Frame = new CGRect(-containerView.Frame.Width, 0, containerView.Frame.Width, containerView.Frame.Height); UIView.Animate(TransitionDuration(transitionContext), () => { fromVC.View.Frame = new CGRect(containerView.Frame.Width, 0, containerView.Frame.Width, containerView.Frame.Height); toVC.View.Frame = containerView.Bounds; }, () => transitionContext.CompleteTransition(true)); } }
内容的提问来源于stack exchange,提问作者user117911
相关产品推荐
相关产品推荐

