Silverlight 教程:使用 VisualStateManager 创建动画导航栏






4.40/5 (6投票s)
一个分步示例,演示如何使用 Silverlight VisualStateManager 创建一个动画导航栏。
本项目最终的成果是一个动画导航栏,类似于 Silverlight.net 网站顶部或我个人网站顶部的导航栏。 通过此链接,您可以查看此教程最终成果的实际工作示例。
引言
本文是一个关于如何使用 Silverlight 2.0 创建动画导航栏的分步教程。本文是系列文章中的第二篇。本系列所有教程的最终成果都是一个非常相似的导航栏,但随着系列中后续文章的更新,我将引入更多 Silverlight 高级概念,让您能够以更优雅、更易于维护的方式完成相同的任务。在第一篇文章中,我向您展示了如何通过手动连接 Storyboards 和鼠标事件来创建导航栏,从而实现所需的动画效果。在本教程中,我将介绍 VisualStateManager,并向您展示第一篇教程中的所有手动工作如何能够被 VisualStateManager 系统的强大功能所取代。
背景
本教程中的项目使用了 Silverlight 2 beta 2、Visual Studio 2008 和 Expression Blend 2.5 的 2008 年 6 月预览版。
分步教程
- 在 VS2008 中,选择一个新项目,一个空网站。将网站命名为 SkinnableNavbar(注意:虽然我将项目命名为“Skinnable”,但本教程特别侧重于演示如何使用 VisualStateManager,并且此 Silverlight 控件在本教程结束时将不会是“可更换皮肤”的;但本教程是我正在撰写的下一篇教程的前提,在该教程中,我们将从这里开始,并真正使控件可更换皮肤。)
- 右键单击解决方案,单击“添加项目”,然后添加一个名为 SkinnableNavbarXap 的 Silverlight 应用程序;勾选“添加测试页”。
- 单击 SkinnableNavbarXap 中的page.xaml,并在 Expression Blend 2.5 中打开它。
- 第一步是创建此控件的所有视觉元素。创建一个看起来像下图所示的内容。它由三条线组成;三个带有渐变的矩形,渐变从亮绿色开始,到透明结束。使用钢笔路径制作三角形。我们将要操作的活动部分是绿色渐变矩形,我们将它们命名为
Nav1Highlight
到Nav3Highlight
,三角形我们将其命名为NavIndicator
,标签我们将其命名为Nav1Label
到Nav3Label
。线条仅用于艺术效果,不是导航栏的活动部分。 - 接下来,我们需要定义用户在与 Nav1、Nav2 或 Nav3 导航项交互时单击或鼠标悬停的区域。为此,在整个 Nav1 区域上方放置一个大矩形,将其不透明度设置为 0,并将其命名为
Nav1ClickTarget
。我们希望用户可以看到要单击的区域,因此使点击目标可见;但重要的是,通过将不透明度设置为 0 来实现此目的,而不是设置为无填充和无描边,因为如果设置为无填充和无描边,它将不会生成鼠标事件,因此显然无法用作点击目标。对 Nav2 和 Nav3 也执行同样的操作。 - 默认情况下,我们将选中 Nav1,因此让我们在视觉上进行设置。选择
Nav2Highlight
并将其可见性设置为折叠,对Nav3Highlight
也执行同样的操作。 - 现在,是时候添加每个状态了。单击状态框中的 + 号,然后添加状态组
MouseOverStates
。单击MouseOverStates
组中的 + 号,然后添加状态Nav1Highlighted
、Nav2Highlighted
和Nav3Highlighted
。 - 现在,我们将定义这些状态各自的外观。单击
Nav2Highlighted
状态。注意工作区周围的红色边框以及右上角的文字“State recording is on”(状态录制已开启)。这正在录制从基准状态到Nav2Highlighted
状态所需的更改。将Nav1Highlight
的可见性设置为折叠,将Nav2Highlight
的可见性设置为可见,并将NavIndicator
移动到 Nav2 下方。结果应与下图相似。单击Nav3Highlight
并进行类似操作。 - 现在,我们将开始将用户操作链接到各种状态。选择
Nav1ClickTarget
,然后在属性面板中转到事件(事件是小闪电符号)。在 MouseEnter 部分,键入Nav1MouseEnter
,然后按 Enter 键。这将启动 VS2008,并在您的 Page.xaml.cs 代码隐藏文件中添加一个Nav1MouseEnter
方法。对Nav2ClickTarget
和 Nav3ClickTarget 执行同样的操作。 - 对于每个方法,添加以下代码,以便 VisualStateManager 根据鼠标进入 ClickTarget 区域的情况,在定义的各个状态之间进行过渡。
- 生成并查看测试页。当您将鼠标悬停在不同区域时,您应该会看到导航栏会定位到
NavIndicator
指向已悬停的项,并且高亮显示会出现。这很酷,而且是演示状态的好方法,但作为动画导航栏来说,它还不够令人满意。让我们进行一些尝试,看看是否能做得更好,添加状态之间的过渡。 - 让我们在
Nav1Highlighted
和Nav2Highlighted
之间添加一个过渡。单击Nav1Highlighted
旁边的 + 号,然后添加过渡。 - 将过渡时间设置为 0.3 秒。保存更改。
- 执行清理项目,然后重新生成,然后查看测试页。当您将鼠标悬停在 Nav2 上时,您应该会看到
NavIndicator
从 Nav1 平滑过渡到 Nav2(而其他所有过渡则直接跳到状态)。问题是平滑过渡在视觉上不够令人满意。我希望有一个加速效果。因此,让我们删除我们在 Expression Blend 中刚刚创建的过渡。为此,请单击Nav2Highlighted
过渡右侧的 - 号。 - 现在,让我们单击
Nav2Highlighted
状态并调整相关 storyboards 以更符合我们的喜好。如果时间轴尚未显示,请通过单击“对象和时间线”面板中状态框旁边的箭头来显示它。将NavIndicator
关键帧移动到 0.3 秒。单击关键帧,然后在 KeySpline 图中将 Easing 设置为 x1 =0, x2=1, y1=1, y2=1,如下图所示。这将使水平(即 x 方向)移动开始缓慢,然后达到全速。生成项目并在测试页中查看它。您应该会看到NavIndicator
过渡到 Nav2 时具有上述类型的运动。请注意,无论您是从 Nav1 还是 Nav3 开始,都可以获得所需的动画效果。这是因为动画 storyboard 效果存在于状态内部,而不是像我们显式定义状态之间的过渡那样是独立的状态。 - 对
Nav3Highlighted
状态重复上述过程,使其NavIndicator
在 0.3 秒内以加速运动动画到位。有趣的是,似乎无法对Nav1Highlighted
状态重复相同的方法,因为出于某种原因,我无法为NavIndicator
关键帧调出 easing KeySpline 图。我无法想到任何合法的理由,这可能是在 Expression Blend 2.5 的 2008 年 6 月预览版本中触发的一个 bug,该 bug 是由NavIndicator
的位置在Base
状态和Nav1Highlighted
状态中相同的事实触发的。为了绕过它,我只是复制了在其他两个状态之一中为NavIndicator
设置动画的DoubleAnimationUsingKeyFrames
XAML,并将其作为 storyboard 粘贴到了Nav1Highlighted
VisualState 下。然后,我将 0.3 秒处的关键帧值更改为 0,表示在 0.3 秒时,我希望NavIndicator
位于 X 位置 0。请注意,在 Silverlight 动画中,对象相对于以它们在基准状态中的原始位置为原点的坐标系进行动画处理。从下面的 XAML 中可以看出,状态只不过是 storyboards,即使它们有时是单帧的 storyboards。 - 现在我们已经让鼠标悬停状态按照我们想要的方式进行了动画处理,最后一件需要做的事情是添加单击时导航到 HTML 页面的功能。突出显示
Nav1ClickTarget
,然后转到属性面板并选择事件图标(带有小闪电符号的那个)。在MouseLeftButtonDown
框中,键入Nav1Clicked
。这将激活 Visual Studio,并在您的代码隐藏文件中添加一个Nav1Clicked
方法。对Nav2ClickTarget
和Nav3ClickTarget
执行同样的操作。 - 在将来的教程中,我将向您展示如何创建一个自定义控件并轻松自定义导航目标,但由于本教程侧重于 VisualStateManager,因此我将硬编码:单击 Nav1 将转到我网站 SilverlightWebApps.com 上的其他教程,Nav2 将转到 yahoo.com,Nav3 将转到 google.com。为此,请将
System.Windows.Browser.HtmlPage.Window.Navigate
调用添加到NavClicked
方法中,如下所示: - 生成并在浏览器中打开测试页。当您将鼠标悬停在 Nav 区域上时,您应该会看到一个
NavIndicator
加速到位,一个NavHighlight
在您将鼠标悬停在 Nav 区域上时闪烁出现,并且当您单击 Nav 区域时,您应该会看到自己导航到不同的 URL。就是这样,您完成了!
private void Nav1MouseEnter(object sender, MouseEventArgs e)
{
VisualStateManager.GoToState(this, "Nav1Highlighted", true);
}
private void Nav2MouseEnter(object sender, MouseEventArgs e)
{
VisualStateManager.GoToState(this, "Nav2Highlighted", true);
}
private void Nav3MouseEnter(object sender, MouseEventArgs e)
{
VisualStateManager.GoToState(this, "Nav3Highlighted", true);
}
<vsm:VisualState x:Name="Nav1Highlighted">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="NavIndicator"
Storyboard.TargetProperty="(UIElement.RenderTransform).(
TransformGroup.Children)[3].(TranslateTransform.X)">
<SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="0">
<SplineDoubleKeyFrame.KeySpline>
<KeySpline ControlPoint1="0,1" ControlPoint2="1,1"/>
</SplineDoubleKeyFrame.KeySpline>
</SplineDoubleKeyFrame>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
private void Nav1Clicked(object sender, MouseButtonEventArgs e)
{
System.Windows.Browser.HtmlPage.Window.Navigate(
new Uri("http://www.silverlightwebapps.com/Tutorials.aspx"));
}
private void Nav2Clicked(object sender, MouseButtonEventArgs e)
{
System.Windows.Browser.HtmlPage.Window.Navigate(new Uri("http://www.yahoo.com"));
}
private void Nav3Clicked(object sender, MouseButtonEventArgs e)
{
System.Windows.Browser.HtmlPage.Window.Navigate(new Uri("http://www.google.com"));
}
历史
- 2008 年 8 月 -- 首次发布。