如何使用视觉状态为 UWP 中控件的可见性设置动画?

How can I animate the visibility of a control in UWP using Visual States?

我目前正在为我的应用程序开发一个自定义控件,它使用 header 展开和折叠内容,您可以单击它来更改状态。它的模板目前看起来像这样。

<Style TargetType="controls:ExpandControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="controls:ExpandControl">
                <Border>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="State">
                            <VisualState x:Name="Visible">
                                <VisualState.Setters>
                                    <Setter Target="Grid.Visibility" Value="Visible" />
                                </VisualState.Setters>
                            </VisualState>

                            <VisualState x:Name="Collapsed">
                                <VisualState.Setters>
                                    <Setter Target="Grid.Visibility" Value="Collapsed" />
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>

                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto" />
                            <RowDefinition Height="*" />
                        </Grid.RowDefinitions>

                        <ContentPresenter x:Name="HeaderPresenter" Content="{TemplateBinding Header}" />

                        <Grid x:Name="Grid" Grid.Row="1">
                            <ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Content}" />
                        </Grid>
                    </Grid>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

正如您从模板中看到的那样,我目前正在使用视觉状态来设置此控件中内容的可见性,但这并不是很好的用户体验,因为内容会消失。

我希望能够以某种方式操纵内容,当控件的可见性发生变化时,内容看起来像是从 header 折叠和展开。

我看过使用 Storyboard 的动画,但我对此完全陌生,如果有人可以提供有关 Storyboard 的一些帮助以及如何使场景为我的控制工作,我将不胜感激!

提前致谢!

故事板在 Visual Studio 中并不是一个绝妙的体验,尝试手动编写它们可能不是最好的主意。

我建议您在 Blend 中打开您的项目,它是 Visual Studio 安装的一部分。它是设计应用程序的绝佳工具,特别是可以非常简单地添加 Storyboard,它会自动为您生成 Storyboard XAML,同时您可以在设计器中看到更改。

至于你的动画场景,我在一个页面中试过你的 XAML 模板,并想出了一些东西,让它看起来像是在折叠和展开,但它没有操纵可见性属性 像这样:

<VisualStateGroup x:Name="State">
    <VisualState x:Name="Visible">
        <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Grid">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="Grid">
                <EasingDoubleKeyFrame KeyTime="0" Value="0"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Grid">
                <DiscreteObjectKeyFrame KeyTime="0">
                    <DiscreteObjectKeyFrame.Value>
                        <Visibility>Collapsed</Visibility>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
                <DiscreteObjectKeyFrame KeyTime="0:0:0.1">
                    <DiscreteObjectKeyFrame.Value>
                        <Visibility>Visible</Visibility>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>

    <VisualState x:Name="Collapsed">
        <Storyboard>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Opacity)" Storyboard.TargetName="Grid">
                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.1" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)" Storyboard.TargetName="Grid">
                <EasingDoubleKeyFrame KeyTime="0" Value="1"/>
                <EasingDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="Grid">
                <DiscreteObjectKeyFrame KeyTime="0">
                    <DiscreteObjectKeyFrame.Value>
                        <Visibility>Visible</Visibility>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
                <DiscreteObjectKeyFrame KeyTime="0:0:0.2">
                    <DiscreteObjectKeyFrame.Value>
                        <Visibility>Collapsed</Visibility>
                    </DiscreteObjectKeyFrame.Value>
                </DiscreteObjectKeyFrame>
            </ObjectAnimationUsingKeyFrames>
        </Storyboard>
    </VisualState>
</VisualStateGroup>

您还需要将内容网格更改为如下所示:

<Grid x:Name="Grid" Grid.Row="1" RenderTransformOrigin="0.5,0">
    <Grid.RenderTransform>
        <CompositeTransform/>
    </Grid.RenderTransform>

    <ContentPresenter x:Name="ContentPresenter" Content="{TemplateBinding Content}" />
</Grid>

我将解释为什么您必须对网格进行更改以及 Storyboard 接下来要做什么。

为了实现类似于您正在寻找的东西,我在您的网格上选择了不透明度和 Y 比例来制作动画。

因为我们将操纵控件的 Y 比例,所以我们将 RenderTransform 添加到 Grid。使用 CompositeTransform 的原因是您可以操作最常见的变换(缩放、旋转、平移等)。

在状态中,我们使用关键帧来跨时间操纵值。这就是您在故事板中实现动画的方式。如果只设置一个时间为 0 的 KeyFrame,它会显示为立即更改,类似于使用更改属性的 VisualState.Setters 机制。

在折叠状态下,我们将网格的不透明度和 Y 缩放比例从 1 更改为 0。这提供了显示内容折叠到 header 中的动画。正如您从关键帧中看到的那样,我们交错了两个属性的动画,以便内容在完成缩放之前淡出。

在可见状态下,我们实质上是通过在相同的时间内将不透明度和 Y 缩放比例从 0 更改为 1 来反转折叠状态。

尝试将它们加载到您的控件中并在 Blend 中进行操作。这是一个很好的起点,因为我很快就把它们放在一起了。

您可以在此处找到有关使用 Blend 制作故事板的更多信息:https://blogs.msdn.microsoft.com/avtarsohi/2016/02/16/understand-storyboard-concept-in-xaml-using-blend-2015/