适用于 Windows 应用的已连接动画

通过连接动画,可以通过对两个不同视图之间的元素转换进行动画处理来创建动态且引人注目的导航体验。 这有助于用户维护其上下文并提供视图之间的连续性。

在连接的动画中,在 UI 内容更改期间,两个视图之间的元素似乎“继续”,从源视图中的位置飞过屏幕,到新视图中的目标。 这强调视图之间的常见内容,并在过渡过程中创建美丽而动态的效果。

WinUI 3 示例集应用程序包括大多数 WinUI 3 控件、特性和功能的交互式示例。 从 Microsoft 应用商店获取应用或在 GitHub 上获取源代码

在此简短视频中,应用使用连接的动画对项目图像进行动画处理,因为它“继续”成为下一页标题的一部分。 效果有助于在整个转换中维护用户上下文。

连接动画

连接的动画和 Fluent 设计系统

Fluent Design System 可帮助你创建包含光线、深度、运动、材料和缩放的现代粗体 UI。 连接动画是 Fluent Design System 组件,可向应用添加动作。 若要了解详细信息,请参阅 Windows 应用设计

为什么连接动画?

在页面之间导航时,用户必须了解导航后显示哪些新内容,以及导航时其意图之间的关系。 连接动画提供了一个强大的视觉隐喻,通过吸引用户的注意力到它们之间共享的内容,从而强调两个视图之间的关系。 此外,连接的动画为页面导航增添视觉兴趣和抛光效果,有助于区分应用的运动设计。

何时使用连接动画

连接动画通常在更改页面时使用,不过它们可应用于在 UI 中更改内容并希望用户维护上下文的任何体验。 每当源视图和目标视图之间共享图像或其他 UI 时,应考虑使用连接的动画而不是 导航转换中的钻取

配置连接的动画

联动动画通过为前进和后退页面导航提供专门定制的动画配置,进一步体现了 Fluent 设计。

通过在 ConnectedAnimation 上设置 Configuration 属性来指定动画配置。 (我们将在下一节中显示此示例。

下表描述了可用的配置。 有关这些动画中应用的运动原理的详细信息,请参阅 方向性和重力

GravityConnectedAnimationConfiguration
这是默认配置,建议进行向前导航。
当用户在应用中向前导航(A 到 B),连接的元素在物理上显示为“拉取页面”。 这样做时,元素似乎在 z 空间中向前移动,并下降一点作为重力保持的效果。 为了克服重力的影响,元素获得速度并加速到其最终位置。 结果是“刻度和浸入”动画。
DirectConnectedAnimationConfiguration
当用户在应用中向后导航(B 到 A),动画更直接。 连接的元素使用减速的立方贝塞尔缓动函数线性地从 B 转换为 A。 向后视觉负担将用户返回其以前的状态,同时仍保持导航流的上下文。
BasicConnectedAnimationConfiguration
这是在 Windows 10 版本 1809(SDK 17763)之前的版本中使用的默认(仅限)动画。

ConnectedAnimationService 配置

ConnectedAnimationService 类有两个应用于单个动画的属性,而不是整个服务。

为了实现各种效果,某些配置忽略 ConnectedAnimationService 上的这些属性,并改用自己的值,如下表所述。

配置 尊重 DefaultDuration? 尊重 DefaultEasingFunction?
重力 是的 是的*
* 从 A 到 B 的基本转换使用此缓动函数,但“重力下降”有自己的缓动函数。
直接 No
动画超过 150 毫秒。
No
使用减速缓动函数。
基本 是的 是的

如何实现连接的动画

设置连接的动画涉及两个步骤:

  1. 在源页上准备动画对象,该对象向系统指示源元素将参与连接的动画。
  2. 目标页上启动动画,传递对目标元素的引用。

从源页导航时,调用 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 的任何后续调用都将失败。

列表和网格体验中的连接动画

通常,需要从列表或网格控件创建连接的动画。 可以在 ListViewGridViewPrepareConnectedAnimationTryStartConnectedAnimationAsync 上使用这两种方法来简化此过程。

例如,假设你有一个 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 });
     }
}

Recommendations

  • 在页面切换中使用连接的动画,其中元素在源页和目标页面之间共享。
  • 使用 GravityConnectedAnimationConfiguration 进行向前导航。
  • 使用 DirectConnectedAnimationConfiguration 进行后退导航。
  • 在准备和启动连接动画之间,不要等待网络请求或其他长时间运行的异步作。 可能需要预先加载必要的信息来提前运行转换,或者在目标视图中加载高分辨率图像时使用低分辨率占位符图像。
  • 如果使用 ConnectedAnimationService,请使用 SuppressNavigationTransitionInfo 防止中的过渡动画,因为连接动画不应与默认导航切换同时使用。 有关如何使用导航转换的详细信息,请参阅 NavigationThemeTransition

UWP 和 WinUI 2

重要

本文中的信息和示例是针对使用 Windows App SDKWinUI 3 的应用优化的,但通常适用于使用 WinUI 2 的 UWP 应用。 有关特定于平台的信息和示例,请参阅 UWP API 参考。

本部分包含在 UWP 或 WinUI 2 应用中使用该控件所需的信息。

ConnectedAnimation

ConnectedAnimationService

NavigationThemeTransition