XAML 中的动画
动画可通过添加动作和交互性来增强应用。 通过使用 Windows 运行时动画库中的动画,你可以将其 Windows 外观集成到你的应用中。 本主题提供了使用每个动画的典型方案的动画和示例汇总。
提示
使用 XAML 的 Windows 运行时控件包含某些类型的动画作为动画库中的内置行为。 通过在你的应用中使用这些控件,无需自己编程,即可获得动画外观。
来自 Windows 运行时动画库的动画提供以下优势:
- 符合动画指南的运动
- 在 UI 状态之间进行快速流畅的过渡,使用户知晓但不会分心
- 向用户指示应用内过渡的视觉行为
例如,当用户将某个项添加到列表时,新项不会立即出现在列表中,而是采用动画形式过渡到相应的位置。 在很短的时间内,列表中的其他项也会采用动画形式移动到它们的新位置,以便为添加的项腾出空间。 此处的过渡行为可使控件更明显地与用户交互。
Windows 10 版本 1607 引入了一个用于实现动画的新 ConnectedAnimationService API,其中某一元素似乎在导航期间在视图之间进行动画处理。 此 API 具有不同于其他动画库 API 的使用模式。 将在参考页面中介绍 ConnectedAnimationService 的用法。
该动画库不会为每个可能方案提供动画。 在某些情况下,你可能希望采用 XAML 创建自定义动画。 有关详细信息,请参阅情节提要动画。
此外,对于根据 ScrollViewer 的滚动位置设置项目动画等某些高级方案,开发人员可能希望使用可视化层互操作来实现自定义动画。 有关详细信息,请参阅可视化层。
动画类型
Windows 运行时动画系统和动画库实现了更大的目标,即允许控件和 UI 的其他部分具备动画行为。 以下是几个不同类型的动画。
- 主题过渡会在 UI 中的某些条件(其中涉及预定义 Windows 运行时 XAML UI 类型的控件或元素)更改时自动应用。 这些称为“主题过渡”,原因是动画支持 Windows 外观,并且定义所有应用从一个交互模式更改为另一个交互模式时为特定 UI 方案执行的操作。 主题过渡是动画库的一部分。
- “主题动画”是具备预定义 Windows 运行时 XAML UI 类型一个或多个属性的动画。 主题动画与主题过渡不同,因为主题动画面向一个特定元素并存在于控件中的特定视觉状态,而主题过渡将分配到存在于视觉状态外部的控件属性并影响这些状态之间的过渡。 许多 Windows 运行时 XAML 控件在情节提要中包含主题动画,这些主题动画是其控件模板的一部分且包含由视觉状态引发的动画。 只要你未修改模板,你都可以将这些内置主题动画用于 UI 中的控件。 但是,如果你替换了模板,则也将删除内置控件主题动画。 若要重新获取它们,你必须在视觉状态的控件集中定义包含主题动画的情节提要。 你也可以从不在视觉状态中的情节提要运行主题动画,并通过 Begin 方法开始运行,但这并不常见。 主题动画是动画库的一部分。
- “视觉转换”会在控件从其定义的视觉状态之一转换到其他状态时应用。 这些是你编写的自定义动画,通常与为控件编写的自定义模板和该模板中的视觉状态定义相关。 该动画仅在两个状态之间的时间运行,这个时间通常很短,最多几秒钟。 有关详细信息,请参阅视觉状态的情节提要动画的“视觉转换”部分。
- 情节提要动画可以随时间推移设置 Windows 运行时依赖属性的值的动画。 情节提要可以定义为可视化过渡的一部分,或者在运行时由应用程序触发。 有关详细信息,请参阅情节提要动画。 有关依赖属性及其所处位置的详细信息,请参阅依赖属性概述。
- 通过新 ConnectedAnimationService API 提供的已连接动画允许开发人员轻松创建以下效果:某一元素似乎在导航期间在视图之间进行动画处理。 从 Windows 10 版本 1607 开始,将提供此 API。 有关详细信息,请参阅 ConnectedAnimationService。
库中提供的动画
动画库提供以下动画。 单击动画的名称即可了解有关其主要使用方案、这些方案的定义方式的详细信息,还可以查看动画示例。
- 页面过渡:在 Frame 中设置页面过渡动画。
- 内容和进入过渡:让一条或一组内容以动画方式进入或退出视图。
- 淡入/淡出和交叉进出:显示过渡元素或控件,或者刷新内容区域。
- 指针向上/向下:提供点击或单击磁贴的视觉反馈。
- 重新定位:将元素移动到新位置。
- 显示/隐藏弹出元素:在视图顶部显示上下文 UI。
- 显示/隐藏边缘 UI:将基于边缘的 UI(包括诸如面板的较大 UI)滑入或滑出视图。
- 列表项更改:从列表中添加或删除某个项目,或者重新排序项目。
- 拖放:在拖放操作期间提供视觉反馈。
页面过渡
使用页面过渡,在应用中设置导航动画。 由于几乎所有应用均会使用某种类型的导航,所以页面过渡动画是应用使用的最常见主题动画类型。 有关页面过渡 API 的详细信息,请参阅 NavigationThemeTransition。
内容过渡和进入过渡
使用内容过渡动画 (ContentThemeTransition) 可以将一条或一组内容移入或移出当前视图。 例如,内容过渡动画显示在首次加载页面时或者在更改页面某部分的内容时,不准备显示的内容。
EntranceThemeTransition 表示可以在首次加载页面或大部分 UI 时应用到内容的动作。 这样,首次出现的内容可以提供不同于对内容的更改的反馈。 EntranceThemeTransition 等同于具有默认参数的 NavigationThemeTransition,但可在 Frame 外部使用。
淡入/淡出和交叉进出
使用淡入和淡出动画可以显示或隐藏过渡 UI 或控件。 在 XAML 中,这些动画将表示为 FadeInThemeAnimation 和 FadeOutThemeAnimation。 一个示例就是在可能会由于用户交互而显示新控件的应用栏中。 另一个示例涉及到临时滚动条或平移指示器,它们将在一段时间内未检测到任何用户输入时淡出。 在随着动态加载内容而从占位符项过渡到最终项时,应用还应使用淡入动画。
使用交叉进出动画可以在某个项的状态发生改变时顺利进行过渡;例如,应用刷新视图的当前内容时。 XAML 动画库不提供专用交叉进出动画(不等效于 crossFade),但是你可以使用 FadeInThemeAnimation 和 FadeOutThemeAnimation 与重叠计时来获取相同的效果。
指针向上/向下
使用 PointerUpThemeAnimation 和 PointerDownThemeAnimation 动画可以为用户成功点击或单击磁贴提供反馈。 例如,当用户单击或点击磁贴时,播放指针向下动画。 释放单击或点击后,播放指针向上动画。
重新放置
使用重新定位动画(RepositionThemeAnimation 或 RepositionThemeTransition)可以将某个元素移动到新位置。 例如,在项目控件中移动标题将使用重新定位动画。
显示/隐藏弹出元素
当你在当前视图顶部显示和隐藏 Popup 或类似的上下文 UI 时,请使用 PopInThemeAnimation 和 PopOutThemeAnimation。 PopupThemeTransition 是主题过渡,如果要轻型消除弹出元素,它是有用的反馈。
显示/隐藏边缘 UI
使用 EdgeUIThemeTransition 动画可以将较小的基于边缘的 UI 滑入和滑出视图。 例如,在屏幕顶部或底部显示自定义应用栏或在屏幕顶部显示用于错误和警告的 UI 表面时使用这些动画。
使用 PaneThemeTransition 动画可显示和隐藏窗格或面板。 此操作适用于基于边缘的较大 UI(例如自定义键盘或任务窗格)。
列表项更改
当你在现有列表中添加或删除某个项目时,将使用 AddDeleteThemeTransition 动画添加动画的表现方式。 若要添加,过渡将首先重新定位列表中的现有项,以便为新项腾出空间,然后添加新项。 若要删除,过渡将从列表中删除项目,然后在移除删除的项目后,重新定位其余的列表项(如有必要)。
还存在一个当某个项目在列表中更改位置时应用的单独 ReorderThemeTransition。 创建该过渡动画与使用关联的删除/添加动画删除某个项和将其添加到新位置中不同。
请注意,这些动画包括在默认 ListView 和 GridView 模板中,因此如果你已使用这些控件,则无需手动添加这些动画。
拖放
使用拖动动画(DragItemThemeAnimation、DragOverThemeAnimation)和放置动画 (DropTargetItemThemeAnimation) 可以在用户拖放一个项时提供视觉反馈。
在激活时,动画将向用户显示该列表可以在放置的项目周围重新排列。 如果用户需要知道在当前位置放下该项目时会将该项目置于列表中的何处,则这样会很有帮助。 动画会提供视觉反馈,表明正在拖动的项目可以放到列表中的其他两个项目之间,以及这些项目将腾出空间。
将动画与自定义控件结合使用
下表概述了在创建这些 Windows 运行时控件的自定义版本时应当使用的动画建议:
UI 类型 | 推荐动画 |
---|---|
对话框 | FadeInThemeAnimation 和 FadeOutThemeAnimation |
浮出控件 | PopInThemeAnimation 和 PopOutThemeAnimation |
工具提示 | FadeInThemeAnimation 和 FadeOutThemeAnimation |
上下文菜单 | PopInThemeAnimation 和 PopOutThemeAnimation |
命令栏 | EdgeUIThemeTransition |
任务窗格或基于边缘的面板 | PaneThemeTransition |
任意 UI 容器的内容 | ContentThemeTransition |
适用于控件或不应用其他动画时 | FadeInThemeAnimation 和 FadeOutThemeAnimation |
过渡动画示例
理想情况下,你的应用使用动画来增强用户界面效果,或使它更具吸引力,而不会使用户觉得厌烦。 能够实现此目的的一种方式是为 UI 应用动画过渡,这样如果某些内容进入或离开了屏幕,或者发生了更改,动画可以提示用户注意所发生的更改。 例如,你的按钮可以快速淡入和淡出视图,而不仅仅是显示和消失。 我们创建了很多 API,可用于创建一致的建议或典型动画过渡。 此处的示例显示了如何为按钮应用动画,以使按钮轻快地滑入视图。
<Button Content="Transitioning Button">
<Button.Transitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Button.Transitions>
</Button>
在此代码中,我们将 EntranceThemeTransition 对象添加到按钮的过渡集中。 现在,首次呈现按钮时,它轻快地滑入视图,而不是突兀地直接显示。 你可以在动画对象上设置一些属性,以调整它滑动的距离以及从什么方向滑动,但是它确实是一个针对特定方案的非常简单的 API,只用于做出引人注目的进入效果。
你也可以在应用的风格资源中定义过渡动画主题,这样可以统一地应用效果。 此示例与前一个示例效果相当,只不过它是使用 Style 来进行应用的:
<UserControl.Resources>
<Style x:Key="DefaultButtonStyle" TargetType="Button">
<Setter Property="Transitions">
<Setter.Value>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<StackPanel x:Name="LayoutRoot">
<Button Style="{StaticResource DefaultButtonStyle}" Content="Transitioning Button"/>
</StackPanel>
前面的示例为一个单独的控件应用了主题过渡,而在对象容器中应用主题过渡时会更有趣。 这样做时,容器的所有子对象都会参与过渡。 在下面的示例中,EntranceThemeTransition 应用到矩形的 Grid 中。
<!-- If you set an EntranceThemeTransition animation on a panel, the
children of the panel will automatically offset when they animate
into view to create a visually appealing entrance. -->
<ItemsControl Grid.Row="1" x:Name="rectangleItems">
<ItemsControl.ItemContainerTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</ItemsControl.ItemContainerTransitions>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Height="400"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- The sequence children appear depends on their order in
the panel's children, not necessarily on where they render
on the screen. Be sure to arrange your child elements in
the order you want them to transition into view. -->
<ItemsControl.Items>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
</ItemsControl.Items>
</ItemsControl>
Grid 的多个子矩形以令人视觉愉悦的方式一个接一个过渡到视图中,而如果你将此动画分别应用到每个矩形,这些矩形将一次全部显示过渡到视图。
下面是此动画的演示:
容器的子对象还可以在其中一个或多个子对象更改位置时重新流动。 在下面的示例中,我们将 RepositionThemeTransition 应用到多个矩形的网格中。 如果你删除其中一个矩形,其他所有矩形将重新流动到新位置。
<Button Content="Remove Rectangle" Click="RemoveButton_Click"/>
<ItemsControl Grid.Row="1" x:Name="rectangleItems">
<ItemsControl.ItemContainerTransitions>
<TransitionCollection>
<!-- Without this, there would be no animation when items
are removed. -->
<RepositionThemeTransition/>
</TransitionCollection>
</ItemsControl.ItemContainerTransitions>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapGrid Height="400"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<!-- All these rectangles are just to demonstrate how the items
in the grid re-flow into position when one of the child items
are removed. -->
<ItemsControl.Items>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
<Rectangle Fill="Red" Width="100" Height="100" Margin="10"/>
</ItemsControl.Items>
</ItemsControl>
private void RemoveButton_Click(object sender, RoutedEventArgs e)
{
if (rectangleItems.Items.Count > 0)
{
rectangleItems.Items.RemoveAt(0);
}
}
// .h
private:
void RemoveButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e);
//.cpp
void BlankPage::RemoveButton_Click(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
if (rectangleItems->Items->Size > 0)
{
rectangleItems->Items->RemoveAt(0);
}
}
你可以将多个过渡动画应用到单个对象或对象容器。 例如,如果你想要矩形列表以动画方式进入视图,而且在更改位置时也采用动画方式,你可以按如下所示应用 RepositionThemeTransition 和 EntranceThemeTransition:
...
<ItemsControl.ItemContainerTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
<RepositionThemeTransition/>
</TransitionCollection>
</ItemsControl.ItemContainerTransitions>
...
在对 UI 元素进行添加、删除、重新排序等操作时,可用多个过渡效果在 UI 元素上创建动画。 这些 API 的名称都包含“ThemeTransition”:
API | 说明 |
---|---|
NavigationThemeTransition | 在 Frame 中提供用于页面导航的 Windows 个性化动画。 |
AddDeleteThemeTransition | 为控件添加或删除子对象或内容的情况提供动画过渡表现方式。 通常,控件是项目容器。 |
ContentThemeTransition | 为控件的内容发生更改的情况提供动画过渡表现方式。 可以在应用 AddDeleteThemeTransition 后再应用它。 |
EdgeUIThemeTransition | 为(较小)边缘 UI 过渡提供动画过渡表现方式。 |
EntranceThemeTransition | 为控件第一次显示的情况提供动画过渡表现方式。 |
PaneThemeTransition | 为(较大边缘 UI)UI 过渡提供动画过渡表现方式。 |
PopupThemeTransition | 提供在控件的弹入组件(例如,对象上类似于工具提示的 UI)显示时应用到它们的动画过渡表现方式。 |
ReorderThemeTransition | 为列表视图控件项目更改顺序的情况提供动画过渡表现方式。 通常它作为拖放操作的结果出现。 不同的控件和主题可能具有不同的动画特征。 |
RepositionThemeTransition | 为控件更改位置的情况提供动画过渡表现方式。 |
主题动画示例
过渡动画的应用很简单。 但是你可能想要对动画效果的计时和顺序进行稍多的控制。 你可以使用主题动画来获得更多的控制,同时对动画的表现方式仍使用一致的主题。 而且,与自定义动画相比,主题动画需要的标记较少。 此处,我们使用 FadeOutThemeAnimation 将一个矩形淡出视图。
<StackPanel>
<StackPanel.Resources>
<Storyboard x:Name="myStoryboard">
<FadeOutThemeAnimation TargetName="myRectangle" />
</Storyboard>
</StackPanel.Resources>
<Rectangle PointerPressed="Rectangle_Tapped" x:Name="myRectangle"
Fill="Blue" Width="200" Height="300"/>
</StackPanel>
// When the user taps the rectangle, the animation begins.
private void Rectangle_Tapped(object sender, PointerRoutedEventArgs e)
{
myStoryboard.Begin();
}
' When the user taps the rectangle, the animation begins.
Private Sub Rectangle_Tapped(sender As Object, e As PointerRoutedEventArgs)
myStoryboard.Begin()
End Sub
//.h
void Rectangle_Tapped(Platform::Object^ sender, Windows::UI::Xaml::Input::PointerRoutedEventArgs^ e);
//.cpp
void BlankPage::Rectangle_Tapped(Object^ sender, PointerRoutedEventArgs^ e)
{
myStoryboard->Begin();
}
与过渡动画不同,主题动画没有自动运行的内置触发器(过渡)。 你必须使用 Storyboard 来包含主题动画,才能在 XAML 中定义它。 还可以更改动画的默认表现方式。 例如,可以通过增加 FadeOutThemeAnimation 上的 Duration 时间值来放缓淡出。
注意 有关显示基本动画技术的用途,我们将通过调用 Storyboard 方法来使用应用代码启动动画。 可以使用 Begin、Stop、Pause 和 Resume Storyboard 方法控制情节提要动画的运行方式。 但是,这并不是你将库动画包含在应用中的典型操作。 相反,你通常将库动画集成到应用于控件或元素的 XAML 样式和模板中。 了解模板和视觉状态会稍微复杂一些。 但是我们介绍了你可以如何使用视觉状态中的库动画,并将其作为视觉状态的情节提要动画主题的一部分。
你可以为 UI 元素应用多个其他主题动画以创建动画效果。 这些 API 的名称都包含“ThemeAnimation”:
API | 说明 |
---|---|
DragItemThemeAnimation | 表示应用到正在拖动的项元素的预配置动画。 |
DragOverThemeAnimation | 表示应用到位于正在拖动的元素下方的元素的预配置动画。 |
DropTargetItemThemeAnimation | 应用到潜在的拖放目标元素的预配置动画。 |
FadeInThemeAnimation | 控件第一次出现时应用到控件的预配置不透明度动画。 |
FadeOutThemeAnimation | 控件从 UI 中删除或隐藏时应用到控件的预配置不透明度动画。 |
PointerDownThemeAnimation | 用于用户点击或单击项目或元素操作的预配置动画。 |
PointerUpThemeAnimation | 用于在用户点击项目或元素并释放该操作后运行的用户操作的预配置动画。 |
PopInThemeAnimation | 控件的弹入组件显示时应用到它们的预配置动画。 此动画结合了不透明度和转换。 |
PopOutThemeAnimation | 控件的弹入组件关闭或删除时应用到它们的预配置动画。 此动画结合了不透明度和转换。 |
RepositionThemeAnimation | 对象重新放置时该对象的预配置动画。 |
SplitCloseThemeAnimation | 使用 ComboBox 打开和关闭样式的动画隐藏目标 UI 的预配置动画。 |
SplitOpenThemeAnimation | 使用 ComboBox 打开和关闭样式的动画显示目标 UI 的预配置动画。 |
DrillInThemeAnimation | 表示在用户在逻辑层次结构中前进(如从列表页到详细信息页)时运行的预配置动画。 |
DrillOutThemeAnimation | 表示在用户在逻辑层次结构中后退(如从详细信息页到列表页)时运行的预配置动画。 |
创建你自己的动画
如果主题动画不能满足你的需求,你可以创建自己的动画。 你可以通过创建一个或多个对象属性值的动画来创建对象的动画。 例如,你可以创建矩形的宽度、RotateTransform 的角度或按钮的颜色值的动画。 我们将此类型的自定义动画称为情节提要动画,用于将其从 Windows 运行时提供为预配置动画类型的库动画中区分出来。 对于情节提要动画,你可以使用可更改特定类型的值的动画(例如 DoubleAnimation 可创建 Double 动画),并将该动画放置在 Storyboard 中以对其进行控制。
为了创建动画,要动画显示的属性必须是依赖属性。 有关依赖属性的详细信息,请参阅依赖属性概述。 有关创建自定义情节提要动画的详细信息,包括如何确定动画目标以及控制动画,请参阅情节提要动画。
XAML(可以在其中定义自定义情节提要动画)中应用 UI 定义的最大领域是在 XAML 中定义控件的视觉状态。 你执行此操作的原因有两个:你要创建一个新控件类;或者你要重新创建现有控件的模板,且该控件的控件模板中具有视觉状态。 有关详细信息,请参阅视觉状态的情节提要动画。