UWP动画重置为起始状态

4
我可以帮你翻译成中文。这段文字是关于编程的。作者在UWP应用程序中使用了一种动画效果,之前在Windows Update 1809之前的版本中都能正常运行。但是在更新后,出现了问题,动画效果在结束后会重置到初始状态。下面给出了一个旋转动画的示例代码。请注意,需要保留HTML标签。
<Storyboard x:Key="FlipTest">
    <DoubleAnimation
                        Storyboard.TargetName="TestRotation"
                        Storyboard.TargetProperty="RotationY"
                        From="180"
                        To="10"
                        Duration="0:0:1.40"
                        />
</Storyboard>

动画项:

    <TextBlock Text="Test" FontSize="18">
        <TextBlock.Projection>
            <PlaneProjection x:Name="TestRotation" RotationY="0" />
        </TextBlock.Projection>
    </TextBlock>

通过按钮点击调用开始:

private void Button_Click(object sender, RoutedEventArgs e)
{
    Storyboard sb = (Storyboard)Resources["FlipTest"];
    sb.Begin();
}

预期行为(在Windows 1803上有效):单击按钮后,TextBlock会旋转并保持在此状态。

在Windows 1809上的行为:动画完成后,在Storyboard.Completed事件被调用之前,TextBox会重置为From(180度)值。

有趣的是,如果我将To="0",它会保持在这个状态。如果我放置10、190或360度,则会重置。请注意,它不会重置为原始状态(即0度),而是重置为From值(180度)。

我还将Microsoft.NETCore.UniversalWindowsPlatform更新到最新版本(6.1.9),但没有改变任何内容。

有人能解释一下这种行为或告诉如何修复它吗?我是否错过了一些显而易见的东西?

更新(丑陋的解决方法)

我发现我可以使用以下丑陋的hack:

    sb.Completed += (s, ee) =>
    {
        TestRotation.RotationY = 0.01; // ugly hack for Windows Build 1809
    };

但不仅在代码中看起来很糟糕。在屏幕上,您可以看到可怕的闪烁,因为动画后该项会重置,然后再次设置为正常值。
我还注意到,在动画完成后RotationY保持正确的值,尽管视觉上该项已旋转。您可以在代码(在完成动画时)或Live Property Explorer中看到该值为0,而在视觉上该项已旋转180度。

1
我已经向相关团队报告了这个问题。他们正在调查中。 - Xie Steven
1
当我在1803和1809上构建时,我遇到了同样的问题。我已经尝试了其他版本,但我猜这是一个已经被忽略的现有bug;但我确信这是一个bug。 - Michael Puckett II
1个回答

4

我认为这是一个bug,与StoryboardFillBehavior有关。

从Windows 10 Build 10240开始就一直存在这个问题。出现这种情况的原因是,如果结果不等于0,则使用FillBehavior.HoldEnd时,状态会被重置为From值而不是Storyboard结束时的To值。

尽管最好查看开放源代码(在我看来),但我已经进行了以下操作,导致我得出这个结论:

验证你已存在的代码是否适用于从Windows 10首次发布以来的各个版本。测试了To = 10To = 0两种情况。To = 10被重置为起始From值,To = 0重置为原始值。这个你已经记录了。

修改From值,使其比To值多360度(使用随机值),以便执行完整的旋转。此时它确实会停在From值处,看起来像是To值,这仅表明Storyboard.FillBehavior = FillBehavior.HoldEnd将保持From值。我知道这不是Storyboard.FillBehavior = FillBehavior.Stop,因为这会在每次Storyboard之前重置为初始值(这就是FillBehavior.Stop应该做的)。

我基于我所做的各种测试(包括手动编写Storyboard)得出这个结论。

假设:

如果Storyboard.FillBehavior = FillBehavior.HoldEnd,并且Storyboard.To值不为0,则完成后它将保持在Storyboard.From值。

如果Storyboard.FillBehavior = FillBehavior.Stop,则它将按预期工作,并返回到动画之前的状态。

建议的解决方法:

虽然我看到你使用了Storyboard.Completed事件的解决方法,但我还有另一种解决方法(尽管仍不理想),这可能更加清晰,并且可以消除闪烁;对我有效。

我已将受影响的Timelines设置为FillBehavior.Stop,然后将它们正在进行动画处理的属性的初始值设置为To值。

注意:在您的示例中,DoubleAnimation.Duration 大于 Storyboard.Duration。这将始终导致它重置为此起始值(在这种情况下为 From 值),因为 DoubleAnimation 永远无法完成。确保您的 Storyboard.Duration 至少与最高子级 Timeline 相同,以防止闪烁和不良效果。
我最初认为这是您的问题,但在将 Storyboard 设置为与或更好的匹配后,您的问题仍然存在。请注意,持续时间的差异可能会导致不希望的结果,特别是当您的Storyboard 短于其子级 Timeline(s) 时。
<Storyboard x:Key="FlipTest"
            Duration="0:0:1.40">
    <DoubleAnimation Storyboard.TargetName="TestRotation"
                     Storyboard.TargetProperty="RotationY"
                     From="180"
                     To="10"
                     Duration="0:0:1.40" 
                     FillBehavior="Stop"/>
</Storyboard>


TestRotation.RotationY = 10;
Storyboard sb = (Storyboard)Resources["FlipTest"];
sb.Begin();

1
非常棒的研究和帮助。你得到了赏金!你的解决方法有效!我需要玩一会儿才能弄清楚什么是重要的。对于那些可能遇到类似问题的人,我需要指出三个关键组件来使解决方法生效:1.将故事板持续时间设置为与“DoubleAnimation”相同。2.仅为有问题的“DoubleAnimation”设置“FillBehaviour =“ Stop””(我在“Storyboard”中有多个)。3.确保“PlanProjection”的“RotationY”值设置为“DoubleAnimation”的“To”值相同(这很重要,如果设置为“From”,它仍然会出现错误)。 - Mike Keskinov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接