我正在尝试通过更改网格的宽度来创建导航抽屉。
XAML:
<Grid x:Name="LayoutRoot" Width="900" Margin="0,0,0,0">
<!--<Grid.ColumnDefinitions>
<ColumnDefinition Width="400"/>
<ColumnDefinition Width="500"/>
</Grid.ColumnDefinitions>-->
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener Flick="OnFlick"/>
</toolkit:GestureService.GestureListener>
<StackPanel Orientation="Horizontal">
<!-- left panel... keep width as 0 when app starts-->
<Grid Name="leftpanel" Width="400">
<StackPanel>
<Image
Source="/Images/dp.png"
Margin="0,40"
x:Name="myimage"
Tap="myimage_Tap"
Height="120"
Width="120"
Stretch="Fill"
RenderTransformOrigin="0.5, 0.5">
<Image.Clip>
<EllipseGeometry
Center="60,60"
RadiusX="60"
RadiusY="60" />
</Image.Clip>
<Image.RenderTransform>
<RotateTransform x:Name="rotateTransform"/>
</Image.RenderTransform>
</Image>
<TextBlock
Foreground="White"
Text="name"
HorizontalAlignment="Center"
Margin="0,-20,0,0"
FontWeight="ExtraBold"/>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Center"
Margin="0,5">
<Image Source="/Images/loc.png"
Height="30"
Width="30"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,30,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="text"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0"
Name="x">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="text"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="Moments"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="text"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="x"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="text"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<Line X1="0" X2="1"
Margin="0,20,0,0"
Stroke="White"
StrokeThickness="1"
Stretch="Fill"
VerticalAlignment="Center"/>
<StackPanel
Orientation="Horizontal"
Height="80">
<Button
BorderThickness="0"
Width="199"
Height="80">
<StackPanel Orientation="Horizontal">
<Image
Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Text="text"
Margin="10,0"
FontSize="35"/>
</StackPanel>
</Button>
<Line X1="0" Y2="100"
Stroke="White"
StrokeThickness="1"
Stretch="Fill"
HorizontalAlignment="Center"/>
<Button
BorderThickness="0"
Width="199"
Height="80">
<StackPanel Orientation="Horizontal">
<Image
Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Text="text"
Margin="10,0"
FontSize="35"/>
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
</Grid>
<Grid Width="500" x:Name="mainpanel" Background="Black">
</Grid>
</StackPanel>
</Grid>
代码背后:
private void OnFlick(object sender, FlickGestureEventArgs e)
{
if (e.Direction == System.Windows.Controls.Orientation.Horizontal)
{
// User flicked towards left ==== show main panel
if (e.HorizontalVelocity < 0)
{
if (leftpanel.Width > 0)
{
Slideright(leftpanel);
}
}
// User flicked towards right ===== show left panel
if (e.HorizontalVelocity > 0)
{
if (leftpanel.Width < 400)
{
Slideleft(leftpanel);
}
}
}
}
private void Slideleft(Grid leftpanel)
{
DoubleAnimation tAnimation = new DoubleAnimation();
tAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.3));
tAnimation.From = 0;
tAnimation.To = 400;
Storyboard.SetTarget(tAnimation, leftpanel);
Storyboard.SetTargetProperty(tAnimation, new PropertyPath(Grid.WidthProperty));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(tAnimation);
storyboard.Begin();
}
private void Slideright(Grid leftpanel)
{
//throw new NotImplementedException();
DoubleAnimation tAnimation = new DoubleAnimation();
tAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.3));
tAnimation.From = 400;
tAnimation.To = 0;
Storyboard.SetTarget(tAnimation, leftpanel);
Storyboard.SetTargetProperty(tAnimation, new PropertyPath(Grid.WidthProperty));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(tAnimation);
storyboard.Begin();
}
这一切都很好,然而,宽度变化的动画很多,有点口吃。无论如何要让它顺利吗?
答案 0 :(得分:1)
我认为最好为RenderTransform
的参数设置动画而不是复杂的控件大小。您的代码中还有太多不必要的网格和堆栈面板会降低您的应用速度。
这是我的修复。翻译动画很流畅,因为它们是由GPU处理的。如果某个动画改变了控件的大小,那么CPU必须参与重新计算每个帧的新布局,所以这很糟糕。我删除了这种动画,并用简单流畅的翻译取而代之。
XAML:
<Grid x:Name="LayoutRoot" Width="900" Margin="0,0,0,0">
<Grid.Resources>
<Storyboard x:Name="SlideLeftAnimation">
<DoubleAnimation Storyboard.TargetName="leftpanel"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
To="-400"
Duration="00:00:00.5">
<DoubleAnimation.EasingFunction>
<QuarticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Name="SlideRightAnimation">
<DoubleAnimation Storyboard.TargetName="leftpanel"
Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
To="0"
Duration="00:00:00.5">
<DoubleAnimation.EasingFunction>
<QuarticEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
</Grid.Resources>
<Grid.Background>
<StaticResource ResourceKey="PhoneBackgroundBrush"/>
</Grid.Background>
<toolkit:GestureService.GestureListener>
<toolkit:GestureListener Flick="OnFlick"/>
</toolkit:GestureService.GestureListener>
<!-- left panel... keep width as 0 when app starts-->
<StackPanel Name="leftpanel" Width="400"
HorizontalAlignment="Left">
<StackPanel.RenderTransform>
<TranslateTransform X="-400"/>
</StackPanel.RenderTransform>
<Image
Source="/Images/dp.png"
Margin="0,40"
x:Name="myimage"
Tap="myimage_Tap"
Height="120"
Width="120"
Stretch="Fill"
RenderTransformOrigin="0.5, 0.5">
<Image.Clip>
<EllipseGeometry
Center="60,60"
RadiusX="60"
RadiusY="60" />
</Image.Clip>
<Image.RenderTransform>
<RotateTransform x:Name="rotateTransform"/>
</Image.RenderTransform>
</Image>
<TextBlock
Foreground="White"
Text="name"
HorizontalAlignment="Center"
Margin="0,-20,0,0"
FontWeight="ExtraBold"/>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Center"
Margin="0,5">
<Image Source="/Images/loc.png"
Height="30"
Width="30"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,30,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="text"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0"
Name="x">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="text"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="Moments"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="text"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="x"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="20,20,0,0">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Foreground="White"
Text="text"
FontSize="35"
Margin="20,0"
HorizontalAlignment="Center"/>
</StackPanel>
<Line X1="0" X2="1"
Margin="0,20,0,0"
Stroke="White"
StrokeThickness="1"
Stretch="Fill"
VerticalAlignment="Center"/>
<StackPanel
Orientation="Horizontal"
Height="80">
<Button
BorderThickness="0"
Width="199"
Height="80">
<StackPanel Orientation="Horizontal">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock
Text="text"
Margin="10,0"
FontSize="35"/>
</StackPanel>
</Button>
<Line X1="0" Y2="100"
Stroke="White"
StrokeThickness="1"
Stretch="Fill"
HorizontalAlignment="Center"/>
<Button BorderThickness="0"
Width="199"
Height="80">
<StackPanel Orientation="Horizontal">
<Image Source="/Images/x.png"
Height="35"
Width="35"/>
<TextBlock Text="text"
Margin="10,0"
FontSize="35"/>
</StackPanel>
</Button>
</StackPanel>
</StackPanel>
<Grid Width="500" x:Name="mainpanel" Background="Black"
HorizontalAlignment="Right">
</Grid>
</Grid>
C#
private void OnFlick(object sender, FlickGestureEventArgs e)
{
if (e.Direction == System.Windows.Controls.Orientation.Horizontal)
{
// User flicked towards left ==== show main panel
if (e.HorizontalVelocity < 0)
{
SlideLeftAnimation.Begin();
}
// User flicked towards right ===== show left panel
else if (e.HorizontalVelocity > 0)
{
SlideRightAnimation.Begin();
}
}
}
如您所见,无需在代码后面创建故事板。在我的示例中,它们都在XAML中作为主Grid
的资源。
请注意,我已将TranslateTransform
添加到您的leftpanel
。这非常重要。
<StackPanel.RenderTransform>
<TranslateTransform X="-400"/>
</StackPanel.RenderTransform>
将X
值设置为0时,面板可见。但是当你把它设置为-400时,它就会向左移动。
答案 1 :(得分:0)
为了在所有动画迭代中使用大量测量和损害性能的内容来控制动画,您应该使用 CacheMode 设置。这将减少性能问题。 这可能会有所帮助。
CacheMode="BitmapCache"
此外,您可以尝试为动画应用不同的缓动功能,因为使用它们可以最大限度地减少实际延迟。最后的建议是关于环境 - 如果在仿真设备上发生这种行为,请尝试在实际连接的设备上重现它,因为仿真永远不是完美的选择。
尝试了你的xaml。我没有看到太多滞后,但似乎动画不是很线性。
我的个人建议 - 尝试最小化xaml容器,在某些情况下,您使用只有一个子节点的stackPanel,因此它们没用,但所有容器在动画时为所有子节点调用度量计算方法。你的xaml填充了带有图像的textblock的复制容器 - 尝试使用新的controltemplate创建样式,这将非常有用(但不是主要目标,并且在该模板上你可以根据需要设置CacheMode - 这只是推荐)。您可以将故事板从代码隐藏提取到xaml,这样它们就可以在没有娱乐的情况下保持静态。
<Grid.Resources>
<Storyboard x:Key="Hide" x:Name="HideAnimation">
<DoubleAnimation Duration="0:0:0.333" From="400" To="0" Storyboard.TargetName="animatedGrid" Storyboard.TargetProperty="Width"/>
</Storyboard>
<Storyboard x:Key="Open" x:Name="OpenAnimation">
<DoubleAnimation Duration="0:0:0.333" From="0" To="400" Storyboard.TargetName="animatedGrid" Storyboard.TargetProperty="Width"/>
</Storyboard>
</Grid.Resources>
在您的特定情况下,动画非常简单,您可以避免重复计算容器元素的措施!只需将 leftPanel 包装在动画网格中(我的xaml storyBoards已经针对 animatedGrid )所以 animatedGrid 不会重新计算度量,因为它有一个固定宽度的孩子。
<Grid Name="animatedGrid" Width="400">
<Grid Name="leftpanel" Width="400">
...
然后你的codeBehind变成了
if (animatedGrid.Width > 0){
HideAnimation.Begin();
}
else{
OpenAnimation.Begin();
}