You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI页面导航动画如何实现从左到右的反向转场?

MAUI页面转场:实现从左到右的前进导航动画

默认情况下,调用GoToAsync并传入true参数会触发从右到左的前进转场动画,若要改为从左到右,可通过以下两种实用技巧实现:

方法一:手动控制导航动画(跨平台通用)

通过拦截默认导航逻辑,手动添加自定义动画实现方向反转:

  1. 在AppShell中注册Navigating事件并注册目标页面路由:
public AppShell()
{
    InitializeComponent();
    Navigating += AppShell_Navigating;
    Routing.RegisterRoute(nameof(DashboardPage), typeof(DashboardPage));
}
  1. 实现事件处理逻辑,自定义转场动画:
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端

  1. 在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>
  1. 在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端

  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 07:01:08