Windows 应用的连贯动画
连贯动画可让你对一个元素在两个不同视图之间的过渡进行动画处理,从而来带来生动且有吸引力的导航体验。 这有助于用户维护其上下文并提供视图之间的连续性。
在连贯动画中,当 UI 内容发生变化时,元素似乎在两种不同视图之间保持“连贯性”,从其在源视图中的位置掠过屏幕,到达它在新视图中的目标位置。 这强调了不同视图之间的共同内容,并创建了转换过程中美观且动态的效果。
示例
WinUI 2 库 | |
---|---|
如果 已安装 WinUI 2 库 应用,请单击此处 打开该应用,并查看“已连接动画”操作。 |
在这段简短的视频中,应用使用连贯动画来为一个正在“继续”变成下一页标题中一部分的项目图像制作动画。 效果有助于在整个转换中维护用户上下文。
连接的动画和 Fluent 设计系统
Fluent Design System 可帮助你创建包含光线、深度、动画、材料和比例的现代粗体 UI。 连接动画是 Fluent Design System 组件,可向应用添加动作。 要了解详细信息,请参阅 Fluent Design 概述。
为什么连接动画?
在页面之间导航时,用户必须了解导航后显示哪些新内容,以及导航时其意图之间的关系。 连接的动画提供了一个强大的视觉隐喻,它通过将用户的焦点绘制到它们之间共享的内容来强调两个视图之间的关系。 此外,连接的动画为页面导航增添视觉兴趣和抛光效果,有助于区分应用的运动设计。
何时使用连接动画
连接动画通常在更改页面时使用,不过它们可应用于在 UI 中更改内容并希望用户维护上下文的任何体验。 每当源视图和目标视图之间共享图像或其他 UI 时,应考虑使用连接的动画而不是 导航转换 中的钻取。
配置连贯动画
重要
此功能要求应用的目标版本为 Windows 10 版本 1809 (SDK 17763) 或更高版本。 Configuration 属性在早期 SDK 中不可用。 可以使用自适应代码或条件 XAML,将低于 SDK 17763 的最低版本作为目标。 有关详细信息,请参阅版本自适应应用。
从 Windows 10 版本 1809 开始,通过提供专为向前和向后翻页导航定制的动画配置,连贯动画进一步体现了 Fluent Design。
可以通过在 ConnectedAnimation 上设置 Configuration 属性来指定动画配置。 (我们将在下一部分中展示这些示例。)
下表介绍了可用配置。 有关这些动画中应用的运动原则的详细信息,请参阅方向性和重心。
GravityConnectedAnimationConfiguration |
---|
这是默认配置,建议用于前进导航。 |
当用户在应用中向后导航时(A 到 B),连贯元素看起来像是“脱离页面”。 在此过程中,元素似乎在 z 空间中向前移动,并由于重力的影响而略微下降。 为了克服重力的影响,元素会获得速度并加速到其最终位置。 结果为“缩放和下降”动画。 |
DirectConnectedAnimationConfiguration |
---|
当用户在应用中向后导航(B 到 A)时,动画更直接。 连贯元素使用减速三次方贝塞尔缓动函数以线性方式从 B 转换为 A。 向后视觉对象提供尽可能快地将用户恢复到以前的状态,同时仍保持导航流的上下文。 |
BasicConnectedAnimationConfiguration |
---|
这是在 Windows 10 版本 1809 (SDK 17763) 之前的版本中使用的默认(且唯一)动画。 |
ConnectedAnimationService 配置
ConnectedAnimationService 类有两个属性,它们应用于单个动画而不是整个服务。
为了实现各种效果,某些配置将忽略 ConnectedAnimationService 上的这些属性,并改为使用自己的值,如下表中所述。
配置 | 是否遵循 DefaultDuration? | 是否遵循 DefaultEasingFunction? |
---|---|---|
引力 | 是 | 是的* *从 A 到 B 的基本转换使用了此缓动函数,但“重力下降”有它自己的缓动函数。 |
直接 | 无 动画持续超过 150 毫秒。 |
无 使用减速缓动函数。 |
基本 | 是 | 是 |
如何实现连贯动画
设置连接的动画涉及两个步骤:
- 准备源页上的动画对象,这向系统表明源元素将参与连贯动画。
- 启动目标页上的动画,将引用传递到目标元素。
在源页中导航时,请调用 ConnectedAnimationService.GetForCurrentView 以获取 ConnectedAnimationService 实例。 要准备动画,请在此实例上调用 PrepareToAnimate,并传入你想要在转换中使用的唯一密钥和 UI 元素。 可以稍后在目标页上检索动画。
ConnectedAnimationService.GetForCurrentView()
.PrepareToAnimate("forwardAnimation", SourceImage);
导航发生时,在目标页中启动动画。 若要启动动画,请调用 ConnectedAnimation.TryStart。 可以通过使用创建动画时提供的唯一键调用 ConnectedAnimationService.GetAnimation 来检索正确的动画实例。
ConnectedAnimation animation =
ConnectedAnimationService.GetForCurrentView().GetAnimation("forwardAnimation");
if (animation != null)
{
animation.TryStart(DestinationImage);
}
前进导航
此示例演示如何使用 ConnectedAnimationService 为两个页面间的前进导航(Page_A 到 Page_B)创建转换。
前进导航的建议动画配置为 GravityConnectedAnimationConfiguration。 这是默认设置,所以不需要设置 Configuration 属性,除非你想指定一个不同的配置。
在源页中设置动画。
<!-- Page_A.xaml -->
<Image x:Name="SourceImage"
HorizontalAlignment="Left" VerticalAlignment="Top"
Width="200" Height="200"
Stretch="Fill"
Source="Assets/StoreLogo.png"
PointerPressed="SourceImage_PointerPressed"/>
// Page_A.xaml.cs
private void SourceImage_PointerPressed(object sender, PointerRoutedEventArgs e)
{
// Navigate to detail page.
// Suppress the default animation to avoid conflict with the connected animation.
Frame.Navigate(typeof(Page_B), null, new SuppressNavigationTransitionInfo());
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
ConnectedAnimationService.GetForCurrentView()
.PrepareToAnimate("forwardAnimation", SourceImage);
// You don't need to explicitly set the Configuration property because
// the recommended Gravity configuration is default.
// For custom animation, use:
// animation.Configuration = new BasicConnectedAnimationConfiguration();
}
在目标页中启动动画。
<!-- Page_B.xaml -->
<Image x:Name="DestinationImage"
Width="400" Height="400"
Stretch="Fill"
Source="Assets/StoreLogo.png" />
// Page_B.xaml.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ConnectedAnimation animation =
ConnectedAnimationService.GetForCurrentView().GetAnimation("forwardAnimation");
if (animation != null)
{
animation.TryStart(DestinationImage);
}
}
后退导航
对于后退导航(Page_B 到 Page_A),请遵循相同的步骤,但会反转源页和目标页。
当用户导航回来时,他们希望应用尽快返回到之前的状态。 因此,建议的配置为 DirectConnectedAnimationConfiguration。 此动画更快、更直接,并使用减速缓动。
在源页中设置动画。
// Page_B.xaml.cs
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
if (e.NavigationMode == NavigationMode.Back)
{
ConnectedAnimation animation =
ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("backAnimation", DestinationImage);
// Use the recommended configuration for back animation.
animation.Configuration = new DirectConnectedAnimationConfiguration();
}
}
在目标页中启动动画。
// Page_A.xaml.cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ConnectedAnimation animation =
ConnectedAnimationService.GetForCurrentView().GetAnimation("backAnimation");
if (animation != null)
{
animation.TryStart(SourceImage);
}
}
在动画设置和启动之间,源元素会在应用的其他 UI 上方呈冻结状态。 这使你可以同时执行其他任何转换动画。 出于此原因,你在两个步骤之间不应等待超过 250 毫秒,因为源元素的存在可能会让人分心。 如果准备动画并在三秒内不启动动画,系统将释放动画,并且对 TryStart 的任何后续调用都将失败。
列表和网格体验中的连接动画
通常,需要从列表或网格控件创建连接的动画。 你可以在 ListView 和 GridView、PrepareConnectedAnimation 和 TryStartConnectedAnimationAsync 上使用这两种方法来简化此过程。
例如,假设你有一个 ListView ,其中包含其数据模板中名称为“PortraitEllipse”的元素。
<ListView x:Name="ContactsListView" Loaded="ContactsListView_Loaded">
<ListView.ItemTemplate>
<DataTemplate x:DataType="vm:ContactsItem">
<Grid>
…
<Ellipse x:Name="PortraitEllipse" … />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
要使用对应于给定列表项目的椭圆准备一个连贯动画,请使用唯一密钥、该项目和名称“PortraitEllipse”调用 PrepareConnectedAnimation 方法。
void PrepareAnimationWithItem(ContactsItem item)
{
ContactsListView.PrepareConnectedAnimation("portrait", item, "PortraitEllipse");
}
若要以该元素为目标启动一个动画,例如从一个详细信息视图返回时,请使用 TryStartConnectedAnimationAsync。 如果刚刚加载 ListView 的数据源,TryStartConnectedAnimationAsync 将等待开始动画,直到创建相应的项容器。
private async void ContactsListView_Loaded(object sender, RoutedEventArgs e)
{
ContactsItem item = GetPersistedItem(); // Get persisted item
if (item != null)
{
ContactsListView.ScrollIntoView(item);
ConnectedAnimation animation =
ConnectedAnimationService.GetForCurrentView().GetAnimation("portrait");
if (animation != null)
{
await ContactsListView.TryStartConnectedAnimationAsync(
animation, item, "PortraitEllipse");
}
}
}
协调动画
一个协调动画是一种特殊类型的进入动画,其中一个元素将与连贯动画目标一并显示,当连贯动画元素在屏幕上移动时创建动画。 协调动画可以向过渡添加更多的视觉兴趣,并进一步吸引用户对源视图和目标视图之间共享的上下文的关注。 在这些图像中,项目的标题 UI 使用协调动画进行动画处理。
当协调动画使用重力配置时,重力将同时应用于连贯动画元素和协调元素。 协调元素将与连贯元素一起“俯冲”,使这些元素保持真正的协调。
使用 TryStart 的双参数重载将协调的元素添加到连接的动画中。 该示例演示了一个名为“DescriptionRoot”且将与名为“CoverImage”的连贯动画一同进入的网格布局的协调动画。
<!-- DestinationPage.xaml -->
<Grid>
<Image x:Name="CoverImage" />
<Grid x:Name="DescriptionRoot" />
</Grid>
// DestinationPage.xaml.cs
void OnNavigatedTo(NavigationEventArgs e)
{
var animationService = ConnectedAnimationService.GetForCurrentView();
var animation = animationService.GetAnimation("coverImage");
if (animation != null)
{
// Don’t need to capture the return value as we are not scheduling any subsequent
// animations
animation.TryStart(CoverImage, new UIElement[] { DescriptionRoot });
}
}
Do's and don'ts
- 在页面切换中使用连接的动画,其中元素在源页和目标页面之间共享。
- 使用 GravityConnectedAnimationConfiguration 进行前进导航。
- 使用 DirectConnectedAnimationConfiguration 进行后退导航。
- 请勿等待准备和启动连贯动画之间的网络请求或其他长时间运行的异步操作。 可能需要预先加载必要的信息来提前运行转换,或者在目标视图中加载高分辨率图像时使用低分辨率占位符图像。
- 如果你正在使用 ConnectedAnimationService,请使用 SuppressNavigationTransitionInfo 来阻止帧中的转换动画,因为连贯动画不应与默认的导航转换同时使用。 有关如何使用导航转换的详细信息,请参阅 NavigationThemeTransition 。