如何在UWP应用XAML中实现类iOS的可反向自定义页面转场动画?
Hey Rick, great question! That iOS-style slide transition (parent page sliding out left, child page sliding in right) is super intuitive, and totally replicable in UWP Frame navigation—including the reverse animation for Frame.GoBack(). Here's a straightforward, step-by-step implementation:
First, turn off the Frame's built-in transitions to avoid conflicts with our custom animation. In your host page (like MainPage.xaml.cs), add this when initializing your Frame:
// Assuming your Frame is named "MainFrame" MainFrame.ContentTransitions = null;
Create a method to handle forward navigation with the slide-in/slide-out effect. This will animate the current page out left while bringing the new page in from the right:
private async Task NavigateToPageWithSlide(Type pageType, object parameter = null) { var currentPage = MainFrame.Content as Page; var newPage = Activator.CreateInstance(pageType) as Page; // Position the new page off-screen to the right initially var newPageTransform = new TranslateTransform { X = Window.Current.Bounds.Width }; newPage.RenderTransform = newPageTransform; // Swap in the new page MainFrame.Content = newPage; // Build and run the animation storyboard var storyboard = new Storyboard(); storyboard.Duration = TimeSpan.FromMilliseconds(300); // Match iOS's typical animation speed var easing = new CubicEase { EasingMode = EasingMode.EaseInOut }; // Animate current page sliding left out of view if (currentPage != null) { var currentTransform = currentPage.RenderTransform as TranslateTransform ?? new TranslateTransform(); currentPage.RenderTransform = currentTransform; var currentSlideAnim = new DoubleAnimation { From = 0, To = -Window.Current.Bounds.Width, EasingFunction = easing }; Storyboard.SetTarget(currentSlideAnim, currentTransform); Storyboard.SetTargetProperty(currentSlideAnim, nameof(TranslateTransform.X)); storyboard.Children.Add(currentSlideAnim); } // Animate new page sliding right into view var newSlideAnim = new DoubleAnimation { From = Window.Current.Bounds.Width, To = 0, EasingFunction = easing }; Storyboard.SetTarget(newSlideAnim, newPageTransform); Storyboard.SetTargetProperty(newSlideAnim, nameof(TranslateTransform.X)); storyboard.Children.Add(newSlideAnim); storyboard.Begin(); await storyboard.CompletedTask; // Clean up old page transform to avoid layout issues currentPage?.RenderTransform = null; }
Create a corresponding method for the back navigation, which reverses the animation: current page slides right out, previous page slides left in:
private async Task GoBackWithSlide() { if (!MainFrame.CanGoBack) return; var currentPage = MainFrame.Content as Page; var previousPage = MainFrame.BackStack.Last().Instance as Page; // Position the previous page off-screen to the left initially var previousTransform = new TranslateTransform { X = -Window.Current.Bounds.Width }; previousPage.RenderTransform = previousTransform; // Trigger the back navigation first MainFrame.GoBack(); // Build and run the reverse animation var storyboard = new Storyboard(); storyboard.Duration = TimeSpan.FromMilliseconds(300); var easing = new CubicEase { EasingMode = EasingMode.EaseInOut }; // Animate current page sliding right out of view var currentTransform = currentPage.RenderTransform as TranslateTransform ?? new TranslateTransform(); currentPage.RenderTransform = currentTransform; var currentSlideAnim = new DoubleAnimation { From = 0, To = Window.Current.Bounds.Width, EasingFunction = easing }; Storyboard.SetTarget(currentSlideAnim, currentTransform); Storyboard.SetTargetProperty(currentSlideAnim, nameof(TranslateTransform.X)); storyboard.Children.Add(currentSlideAnim); // Animate previous page sliding left into view var previousSlideAnim = new DoubleAnimation { From = -Window.Current.Bounds.Width, To = 0, EasingFunction = easing }; Storyboard.SetTarget(previousSlideAnim, previousTransform); Storyboard.SetTargetProperty(previousSlideAnim, nameof(TranslateTransform.X)); storyboard.Children.Add(previousSlideAnim); storyboard.Begin(); await storyboard.CompletedTask; // Clean up old page transform currentPage.RenderTransform = null; }
Instead of calling MainFrame.Navigate(...) directly, use your new navigation method:
// Navigate to a subpage with the slide effect await NavigateToPageWithSlide(typeof(YourSubPage)); // Go back with reverse slide effect await GoBackWithSlide();
If your app supports resizing, add a listener to adjust animation values when the window size changes:
Window.Current.SizeChanged += (s, e) => { // Update any stored width values or adjust ongoing animations here };
This implementation gives you that smooth, familiar iOS-style transition while working natively within UWP's Frame system. Let me know if you run into any kinks!
内容的提问来源于stack exchange,提问作者Rick Engle

