我正在使用 UWP 并使用 Composition API 以编程方式在屏幕上滑动项目,我发现当应用程序第一次启动时,许多元素的初始滑动都无法正确执行。经过进一步检查,我发现我用于计算和设置动画初始位置和目标位置的 ElementVisual 的偏移属性有时会在第一个动画上为 X、Y、Z 值提供全零值。只要应用程序继续运行,我就可以说从那时起该元素的所有动画都可以正常工作。
我正在开发的应用程序更加复杂和有趣,但我创建了一个简化的测试应用程序来演示我遇到的问题。
从一个新的空白 UWP 项目中,我将以下 GridView 和 Button 添加到页面的根网格:
<GridView x:Name="TestGridView" HorizontalAlignment="Center" VerticalAlignment="Center">
<GridViewItem >
<Border Width="125" Height="125">
<Grid>
<TextBlock Text="Content String 1" />
</Grid>
</Border>
</GridViewItem>
<GridViewItem>
<Border Width="125" Height="125">
<Grid>
<TextBlock Text="Content String 2" />
</Grid>
</Border>
</GridViewItem>
<GridViewItem>
<Border Width="125" Height="125">
<Grid>
<TextBlock Text="Content String 3"/>
</Grid>
</Border>
</GridViewItem>
</GridView>
<Button Height="125" Width="125" Click="Button_Click"/>
在代码隐藏文件中,我添加了以下附加 using 语句、变量声明和此事件处理程序:
using System.Numerics;
using Windows.UI.Composition;
using Windows.UI.Xaml.Hosting;
using System.Diagnostics;
Compositor compositor;
private void Button_Click(object sender, RoutedEventArgs e)
{
foreach (var element in TestGridView.ItemsPanelRoot.Children)
{
var slideVisual = ElementCompositionPreview.GetElementVisual(element);
Debug.WriteLine("Element Offset: " + slideVisual.Offset);
var slideAnimation = compositor.CreateVector3KeyFrameAnimation();
slideAnimation.InsertKeyFrame(0f, slideVisual.Offset);
slideAnimation.InsertKeyFrame(1f, new Vector3(slideVisual.Offset.X, slideVisual.Offset.Y + 20f, 0f));
slideAnimation.Duration = TimeSpan.FromMilliseconds(800);
slideVisual.StartAnimation(nameof(slideVisual.Offset), slideAnimation);
}
}
我还在 MainPage() 构造函数中初始化了合成器:
public MainPage()
{
this.InitializeComponent();
compositor = ElementCompositionPreview.GetElementVisual(this).Compositor;
}
然后我从 Visual Studio 以调试模式运行项目。按下按钮会在我的即时窗口中产生以下输出(为清楚起见,在编辑中添加了分隔线)
Element Offset: <0, 0, 0>
Element Offset: <0, 0, 0>
Element Offset: <0, 0, 0>
Element Offset: <0, 20, 0>
Element Offset: <129, 0, 0>
Element Offset: <258, 0, 0>
Element Offset: <0, 40, 0>
Element Offset: <129, 20, 0>
Element Offset: <258, 20, 0>
Element Offset: <0, 60, 0>
Element Offset: <129, 40, 0>
Element Offset: <258, 40, 0>
请注意,三个元素中的第一个在第一张幻灯片上确实有动画,但其他两个没有,并且它们的 Offset 值都是零值。
在每张幻灯片上,所有三个元素都从它们之前的位置开始动画,尽管第一张幻灯片动画的副作用仍然存在。
我试图找到一种方法来强制我们应用程序中的元素更新它们的偏移值,以便每个元素的初始幻灯片动画正常工作,包括在实际预期动画之前插入一个虚拟的 WarmUp 动画,这很快告诉我,但没有成功元素要么从其当前位置移动到相同的位置,要么稍微修改开始位置到它的实际当前位置。
var warmUpAnimation = compositor.CreateVector3KeyFrameAnimation();
warmUpAnimation.InsertKeyFrame(0.0f, new Vector3(slideVisual.Offset.X + 1, slideVisual.Offset.Y, slideVisual.Offset.Z));
warmUpAnimation.InsertKeyFrame(1f, slideVisual.Offset);
warmUpAnimation.Duration = TimeSpan.FromMilliseconds(1);
我猜这是 Windows 组合 API 中的一个错误,但我希望有人能提出一个简单有效的解决方法,这将迫使 ElementVisual 在加载后正确初始化。