我应该使用哪些布局元素来实现带有动画过渡的子菜单
Which layout elements should I use to implement a submenu with an animation transition
我对这个 WinRT 和 XAML 东西还很陌生,不确定如何实现这个目标。对于我的页面布局,我基本上有 2 行。第一行代表我的(静态)基本菜单,带有一些按钮和图片(大约 130 高度)。屏幕的其余部分应该用于显示内容。像这样:
现在,当用户单击主菜单按钮时,子菜单 "filter settings" 应该会随着动画向下移动。主要内容也响应此事件并相应移动("filter settings" 不应覆盖主要内容)。
我目前定义此布局的想法是使用一个包含 3 行和 2 个框架的网格。当没有过滤器被激活时,我使用 rowspan 让我的主要内容跨越整个区域。当识别到单击事件时,我将包含主要内容 (ModuleContentFrame) 的框架的行数更改为 2,并将其行跨度更改为 1。然后我将过滤页面加载到框架 ModuleFadeInFrame。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="130"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Frame
x:Name="ModuleFadeInFrame"
Grid.Row="1"/>
<Frame
x:Name="ModuleContentFrame"
Grid.Row="1"
Grid.RowSpan="2"/>
</Grid>
我的问题是:这个内部有网格和框架的布局定义是否适合解决这个问题?如何在显示子菜单时实现 "moving" 动画。我用 Storyboard 尝试了这个,但主要内容只是 "jumping" 到第 2 行
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ModuleContentFrame"
Storyboard.TargetProperty="(Grid.Row)">
<DiscreteObjectKeyFrame KeyTime="1" Value="2" />
</ObjectAnimationUsingKeyFrames>
您无法真正为网格设置动画 row/col/etc... 更改。此外,任何会导致布局更改的动画都是依赖动画 - 并且性能不佳。我会做的是这样的:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
x:Class="App1.MainPage"
mc:Ignorable="d">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MenuState">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3">
<VisualTransition.GeneratedEasingFunction>
<ExponentialEase EasingMode="EaseInOut"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="ClosedState"/>
<VisualState x:Name="OpenState">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="grid" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid Margin="0,50,0,0" Background="Black">
<TextBlock>
Long text blablabla
</TextBlock>
</Grid>
<Grid x:Name="grid" Margin="0,50,0,0" Height="50" VerticalAlignment="Top" Background="#77ffff00">
<Grid.RenderTransform>
<CompositeTransform TranslateY="-50"/>
</Grid.RenderTransform>
<Button Content="Close" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:GoToStateAction StateName="ClosedState"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
</Grid>
<Grid Margin="0,0,0,0" Height="50" VerticalAlignment="Top" Background="Red">
<Button Content="Open" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:GoToStateAction StateName="OpenState"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
</Grid>
</Grid>
</Grid>
</Page>
这样就不会改变布局,因为您的子菜单最终会位于内容之上。
如果你真的坚持'not obscuring content'方式
您可以在内容之前使用 Height="0"
设置子菜单,并使用 DoubleAnimation
设置元素高度的动画。如果这样做,则必须将 EnableDependentAnimation
设置为 true。
谢谢你 Tamás,你帮了我很多,让我得到了解决方案。我现在这样做如下:
此代码进入每个子菜单的 edit:UserControl。在主页上,我只需要处理我的 Button 单击事件并调用适当的动画。下一步是按照您的建议熟悉 Blend :-)
我将你的 post 标记为答案,因为它对我找到解决方案最有帮助
<Grid x:Name="maingrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Grid.RenderTransform>
<CompositeTransform TranslateY="-360"/>
</Grid.RenderTransform>
<Grid.Resources>
<Storyboard x:Name="myStoryboardOpen">
<DoubleAnimation Duration="0:0:0.3" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="maingrid"
d:IsOptimized="True"/>
</Storyboard>
<Storyboard x:Name="myStoryboardClose">
<DoubleAnimation Duration="0:0:0.3" To="-360" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="maingrid"
d:IsOptimized="True"/>
</Storyboard>
</Grid.Resources>
我对这个 WinRT 和 XAML 东西还很陌生,不确定如何实现这个目标。对于我的页面布局,我基本上有 2 行。第一行代表我的(静态)基本菜单,带有一些按钮和图片(大约 130 高度)。屏幕的其余部分应该用于显示内容。像这样:
现在,当用户单击主菜单按钮时,子菜单 "filter settings" 应该会随着动画向下移动。主要内容也响应此事件并相应移动("filter settings" 不应覆盖主要内容)。
我目前定义此布局的想法是使用一个包含 3 行和 2 个框架的网格。当没有过滤器被激活时,我使用 rowspan 让我的主要内容跨越整个区域。当识别到单击事件时,我将包含主要内容 (ModuleContentFrame) 的框架的行数更改为 2,并将其行跨度更改为 1。然后我将过滤页面加载到框架 ModuleFadeInFrame。
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="130"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="2*"/>
</Grid.RowDefinitions>
<Frame
x:Name="ModuleFadeInFrame"
Grid.Row="1"/>
<Frame
x:Name="ModuleContentFrame"
Grid.Row="1"
Grid.RowSpan="2"/>
</Grid>
我的问题是:这个内部有网格和框架的布局定义是否适合解决这个问题?如何在显示子菜单时实现 "moving" 动画。我用 Storyboard 尝试了这个,但主要内容只是 "jumping" 到第 2 行
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ModuleContentFrame"
Storyboard.TargetProperty="(Grid.Row)">
<DiscreteObjectKeyFrame KeyTime="1" Value="2" />
</ObjectAnimationUsingKeyFrames>
您无法真正为网格设置动画 row/col/etc... 更改。此外,任何会导致布局更改的动画都是依赖动画 - 并且性能不佳。我会做的是这样的:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:Interactivity="using:Microsoft.Xaml.Interactivity" xmlns:Core="using:Microsoft.Xaml.Interactions.Core"
x:Class="App1.MainPage"
mc:Ignorable="d">
<Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="MenuState">
<VisualStateGroup.Transitions>
<VisualTransition GeneratedDuration="0:0:0.3">
<VisualTransition.GeneratedEasingFunction>
<ExponentialEase EasingMode="EaseInOut"/>
</VisualTransition.GeneratedEasingFunction>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="ClosedState"/>
<VisualState x:Name="OpenState">
<Storyboard>
<DoubleAnimation Duration="0" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)" Storyboard.TargetName="grid" d:IsOptimized="True"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Grid Margin="0,50,0,0" Background="Black">
<TextBlock>
Long text blablabla
</TextBlock>
</Grid>
<Grid x:Name="grid" Margin="0,50,0,0" Height="50" VerticalAlignment="Top" Background="#77ffff00">
<Grid.RenderTransform>
<CompositeTransform TranslateY="-50"/>
</Grid.RenderTransform>
<Button Content="Close" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:GoToStateAction StateName="ClosedState"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
</Grid>
<Grid Margin="0,0,0,0" Height="50" VerticalAlignment="Top" Background="Red">
<Button Content="Open" >
<Interactivity:Interaction.Behaviors>
<Core:EventTriggerBehavior EventName="Click">
<Core:GoToStateAction StateName="OpenState"/>
</Core:EventTriggerBehavior>
</Interactivity:Interaction.Behaviors>
</Button>
</Grid>
</Grid>
</Grid>
</Page>
这样就不会改变布局,因为您的子菜单最终会位于内容之上。
如果你真的坚持'not obscuring content'方式
您可以在内容之前使用 Height="0"
设置子菜单,并使用 DoubleAnimation
设置元素高度的动画。如果这样做,则必须将 EnableDependentAnimation
设置为 true。
谢谢你 Tamás,你帮了我很多,让我得到了解决方案。我现在这样做如下:
此代码进入每个子菜单的 edit:UserControl。在主页上,我只需要处理我的 Button 单击事件并调用适当的动画。下一步是按照您的建议熟悉 Blend :-)
我将你的 post 标记为答案,因为它对我找到解决方案最有帮助
<Grid x:Name="maingrid" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
<Grid.RenderTransform>
<CompositeTransform TranslateY="-360"/>
</Grid.RenderTransform>
<Grid.Resources>
<Storyboard x:Name="myStoryboardOpen">
<DoubleAnimation Duration="0:0:0.3" To="0" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="maingrid"
d:IsOptimized="True"/>
</Storyboard>
<Storyboard x:Name="myStoryboardClose">
<DoubleAnimation Duration="0:0:0.3" To="-360" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateY)"
Storyboard.TargetName="maingrid"
d:IsOptimized="True"/>
</Storyboard>
</Grid.Resources>