增强现有 ScrollViewer 体验

本文介绍如何使用 WinUI XAML ScrollViewer 和 ExpressionAnimations 创建动态输入驱动的运动体验。

先决条件

此处,我们假设你熟悉以下文章中讨论的概念:

为什么在 ScrollViewer 的基础上生成?

通常,使用现有的 XAML ScrollViewer 为应用内容创建可滚动且可缩放的图面。 随着 Fluent Design 语言的引入,你现在还应该专注于如何使用滚动或缩放图面的行为来驱动其他运动体验。 例如,使用滚动来推动后台的模糊动画或推动“粘滞标头”的位置。

在这些方案中,你将利用滚动和缩放等行为或操作体验,使应用的其他部分更加动态。 这些反过来又使应用感觉更加凝聚力,使体验在最终用户眼中更加令人难忘的。 通过使应用 UI 更加令人难忘的是,最终用户将更频繁地和更长的时间与应用互动。

可以在 ScrollViewer 的基础上构建哪些内容?

可以利用 ScrollViewer 的位置来生成许多动态体验:

  • 视差 – 使用 ScrollViewer 位置以相对滚动位置的速率移动背景或前景内容。
  • StickyHeaders – 使用 ScrollViewer 的位置对标题进行动画处理,并将标题“粘附”到某个位置
  • 输入驱动的效果 – 使用 Scrollviewer 的位置来实现 Composition 效果,如模糊。

通常,通过使用 ExpressionAnimation 引用 ScrollViewer 的位置,可以创建动态更改相对于滚动量的动画。

具有视差的列表视图

隐藏的标题

使用 ScrollViewerManipulationPropertySet

若要使用 XAML ScrollViewer 创建这些动态体验,必须能够引用动画中的滚动位置。 这是通过访问 XAML ScrollViewer 的名为 ScrollViewerManipulationPropertySet 的 CompositionPropertySet 实现的。 ScrollViewerManipulationPropertySet 包含一个名为 Translation 的 Vector3 属性,该属性提供对 ScrollViewer 滚动位置的访问权限。 然后可以在 ExpressionAnimation 中像引用任何其他 CompositionPropertySet 一样引用此属性。

入门的常规步骤:

  1. 通过 ElementCompositionPreview 访问 ScrollViewerManipulationPropertySet。
    • ElementCompositionPreview.GetScrollViewerManipulationPropertySet(ScrollViewer scroller)
  2. 创建一个 ExpressionAnimation,该表达式引用 PropertySet 中的 Translation 属性。
    • 不要忘记设置引用参数!
  3. 使用 ExpressionAnimation 定位 CompositionObject 的属性。

注释

建议将 GetScrollViewerManipulationPropertySet 方法返回的 PropertySet 分配给类变量。 这将确保该属性集不会作为垃圾回收,因此对于引用了它的 ExpressionAnimation 不会产生任何影响。 ExpressionAnimations 不保持对公式中使用的任何对象的强引用。

示例

让我们看看上面所示的视差样本是如何组合在一起的。 ParallaxingListItems 示例包含此体验的源代码。

第一件事是获取对 ScrollViewerManipulationPropertySet 的引用。

_scrollProperties =
    ElementCompositionPreview.GetScrollViewerManipulationPropertySet(myScrollViewer);

下一步是创建 ExpressionAnimation,以定义一个公式,该公式利用 ScrollViewer 的滚动位置。

_parallaxExpression = compositor.CreateExpressionAnimation();
_parallaxExpression.SetScalarParameter("StartOffset", 0.0f);
_parallaxExpression.SetScalarParameter("ParallaxValue", 0.5f);
_parallaxExpression.SetScalarParameter("ItemHeight", 0.0f);
_parallaxExpression.SetReferenceParameter("ScrollManipulation", _scrollProperties);
_parallaxExpression.Expression = "(ScrollManipulation.Translation.Y + StartOffset - (0.5 * ItemHeight)) * ParallaxValue - (ScrollManipulation.Translation.Y + StartOffset - (0.5 * ItemHeight))";

注释

还可以利用 ExpressionBuilder 帮助程序类来构造此相同的表达式,而无需字符串:

var scrollPropSet = _scrollProperties.GetSpecializedReference<ManipulationPropertySetReferenceNode>();
var parallaxValue = 0.5f;
var parallax = (scrollPropSet.Translation.Y + startOffset);
_parallaxExpression = parallax * parallaxValue - parallax;

最后,使用此 ExpressionAnimation 并以需要视差处理的 Visual 为目标。 在这种情况下,它是列表中每个项的图像。

Visual visual = ElementCompositionPreview.GetElementVisual(image);
visual.StartAnimation("Offset.Y", _parallaxExpression);