改变网格高度的滞后动画

时间:2015-03-07 12:23:02

标签: c# xaml animation windows-phone-8

我正在尝试通过更改网格的宽度来创建导航抽屉。

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();



    }

这一切都很好,然而,宽度变化的动画很多,有点口吃。无论如何要让它顺利吗?

2 个答案:

答案 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();
}