如何使用Visual States为UWP中的控件的可见性设置动画?

时间:2016-11-20 13:18:50

标签: xaml animation uwp visualstatemanager

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

<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>

正如您从模板中看到的,我目前正在使用视觉状态来设置此控件中内容的可见性,但由于内容刚刚消失,因此用户体验不佳。

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

我已经使用Storyboard查看了动画,但我对此完全陌生,如果有人可以在Storyboard上提供一些帮助以及我如何使该方案适合我的控制,那将非常非常感谢!

提前致谢!

1 个答案:

答案 0 :(得分:3)

故事板在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>

我将解释为什么您必须对网格进行更改以及故事板下一步做什么。

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

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

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

在折叠状态下,我们将网格的不透明度和Y缩放从1更改为0.这样可以显示内容折叠到标题中的动画。正如您从关键帧中看到的那样,我们错开了两个属性的动画,因此内容在完成操作缩放之前就会淡出。

在Visible状态下,我们基本上通过在相同的时间内将不透明度和Y缩放从0更改为1来反转折叠状态。

尝试将这些加载到您的控件中并在Blend中与它们一起玩。这是一个很好的起点,因为我很快就把它扔到了一起。

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