有时候我们需要编写一些迎合IOS用户使用习惯的uwp应用,我在这里整理一下仿IOS页面切换效果的代码。
先分析IOS的页面切换。用户使用左右滑动方式进行前进和后退,播放类似于FlipView的切换动画。导航到新页面时,使用页面前进的动画。
UWP自带很多切换效果,位于 Windows.UI.Xaml.Media.Animation 中。与苹果的切换效果最接近的是 PaneThemeTransition (而不是EdgeUIThemeTransition)。
PaneThemeTransition的效果是从它的Edge属性规定的方位平移进入,从Edge属性规定的方位平移退出。
苹果的切换方式是:
新建和前进:从右边平移进入,从左边平移退出。
返回:从左边平移进入,从右边平移退出。
分析完这些,大致的实现步骤就明了了。
在页面初始化时添加PaneThemeTransition
在进入动画播放前判断导航方式并设定Edge属性。不考虑刷新这种情况,如果是返回就是Left,否则是Right。
在退出动画播放前判断导航方式并设定Edge属性。不考虑刷新这种情况,如果是返回就是Right,否则是Left。
照这个思路写出来的代码是这样的:
VB
1 Imports Windows.UI.Xaml.Media.Animation 2 ''' <summary> 3 ''' 移植苹果的应用时使用。这种页面自带苹果导航动画和手势。 4 ''' </summary> 5 Public MustInherit Class AppleAnimationPage 6 Inherits Page 7 Dim PaneAnim As New PaneThemeTransition With {.Edge = EdgeTransitionLocation.Right} 8 Sub New() 9 MyBase.New 10 Transitions = New TransitionCollection 11 Transitions.Add(PaneAnim)
12 End Sub 13 Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs) 14 PaneAnim.Edge = If(e.NavigationMode = NavigationMode.Back, EdgeTransitionLocation.Left, EdgeTransitionLocation.Right) 15 MyBase.OnNavigatedTo(e) 16 End Sub 17 Protected Overrides Sub OnNavigatingFrom(e As NavigatingCancelEventArgs) 18 PaneAnim.Edge = If(e.NavigationMode <> NavigationMode.Back, EdgeTransitionLocation.Left, EdgeTransitionLocation.Right) 19 MyBase.OnNavigatingFrom(e) 20 End Sub 21 End Class
接下来是写手势代码。首先设置一下手势的模式为横向平移,然后对ManipulationCompleted事件进行处理。这里判断的逻辑是不唯一的。我自己想了一种判断的方法,代码写上之后是这样的:
VB
1 Imports Windows.UI.Xaml.Media.Animation 2 ''' <summary> 3 ''' 移植苹果的应用时使用。这种页面自带苹果导航动画和手势。 4 ''' </summary> 5 Public MustInherit Class AppleAnimationPage 6 Inherits Page 7 Dim PaneAnim As New PaneThemeTransition With {.Edge = EdgeTransitionLocation.Right} 8 Sub New() 9 MyBase.New 10 Transitions = New TransitionCollection 11 Transitions.Add(PaneAnim) 12 ManipulationMode = ManipulationModes.TranslateX 13 End Sub 14 Protected Overrides Sub OnNavigatedTo(e As NavigationEventArgs) 15 PaneAnim.Edge = If(e.NavigationMode = NavigationMode.Back, EdgeTransitionLocation.Left, EdgeTransitionLocation.Right) 16 MyBase.OnNavigatedTo(e) 17 End Sub 18 Protected Overrides Sub OnNavigatingFrom(e As NavigatingCancelEventArgs) 19 PaneAnim.Edge = If(e.NavigationMode <> NavigationMode.Back, EdgeTransitionLocation.Left, EdgeTransitionLocation.Right) 20 MyBase.OnNavigatingFrom(e) 21 End Sub 22 Private Sub AppleAnimationPage_ManipulationCompleted(sender As Object, e As ManipulationCompletedRoutedEventArgs) Handles Me.ManipulationCompleted 23 Dim trans = e.Cumulative.Translation 24 Dim DeltaX As Double = Math.Abs(trans.X) 25 If Math.Abs(trans.Y) * 3 < DeltaX AndAlso DeltaX > ActualWidth / 2 Then 26 If trans.X > 0 Then 27 If Frame.CanGoBack Then Frame.GoBack() 28 Else 29 If Frame.CanGoForward Then Frame.GoForward() 30 End If 31 End If 32 End Sub 33 End Class
这些代码在我的Lumia 1520和屏幕9英寸的平板进行过测试,有比较理想的切换效果。
底下评论有人需要c#代码,转换后的在这里:
C#
using System; using System.Collections; using System.Collections.Generic; using System.Data; using System.Diagnostics; using Windows.UI.Xaml.Media.Animation; // 此代码使用 SharpDevelop 4.4 转换 // 要用的话自己加上命名空间。因为c#项目要求自己写一个与项目的根命名空间符合的命名空间 /// <summary> /// 移植苹果的应用时使用。这种页面自带苹果导航动画和手势。 /// </summary> public abstract class AppleAnimationPage : Page { PaneThemeTransition PaneAnim = new PaneThemeTransition { Edge = EdgeTransitionLocation.Right }; public AppleAnimationPage() : base() { ManipulationCompleted += AppleAnimationPage_ManipulationCompleted; Transitions = new TransitionCollection(); Transitions.Add(PaneAnim); ManipulationMode = ManipulationModes.TranslateX; } protected override void OnNavigatedTo(NavigationEventArgs e) { PaneAnim.Edge = e.NavigationMode == NavigationMode.Back ? EdgeTransitionLocation.Left : EdgeTransitionLocation.Right; base.OnNavigatedTo(e); } protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) { PaneAnim.Edge = e.NavigationMode != NavigationMode.Back ? EdgeTransitionLocation.Left : EdgeTransitionLocation.Right; base.OnNavigatingFrom(e); } private void AppleAnimationPage_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) { var trans = e.Cumulative.Translation; double DeltaX = Math.Abs(trans.X); if (Math.Abs(trans.Y) * 3 < DeltaX && DeltaX > ActualWidth / 2) { if (trans.X > 0) { if (Frame.CanGoBack) Frame.GoBack(); } else { if (Frame.CanGoForward) Frame.GoForward(); } } } }