c#UWP中的滑动元素

时间:2017-08-03 13:15:43

标签: c# xaml animation uwp slide

我对UWP中的动画有疑问。我希望在我的应用程序底部有一个菜单,当点击顶部时,向上滑动(显示)或向下滑动(几乎完全隐藏)。我之前和之前都在学习WPF,我知道我可以使用ThicknessAnimation来移动我的控制边缘并让它滑动。不幸的是,在UWP中,我不能使用ThicknessAnimations,所以我试图寻找另一种方法。我希望这适用于任意FrameworkElement(以便能够重用它)。最终,我提出了这个解决方案:

    /// <summary>
    /// Adds a vertical slide animation
    /// </summary>
    /// <param name="storyboard">The storyboard to add the animation to</param>
    /// <param name="seconds">The time the animation will take</param>
    /// <param name="offset">The distance the element will cover (nagative is up, positive is down)</param>
    public static void AddVerticalSlide(this Storyboard storyboard, FrameworkElement element, float seconds, double offset)
    {

        var slideAnimation = new ObjectAnimationUsingKeyFrames();       

        for (int i = 0; i <= 100; ++i)
        {
            double scalar = (double)i / 100;
            slideAnimation.KeyFrames.Add(new DiscreteObjectKeyFrame
            {                   
                Value = new Thickness(0, scalar*offset, 0, -scalar*offset),
                KeyTime = TimeSpan.FromSeconds(scalar*seconds),
            });
        }   

        //slideAnimation.Duration = TimeSpan.FromSeconds(seconds);

        // Set the target and target property
        Storyboard.SetTarget(slideAnimation, element);
        Storyboard.SetTargetProperty(slideAnimation, "(FrameworkElement.Margin)");

        // Add the animation to the storyboard
        storyboard.Children.Add(slideAnimation);
    }

它有效,看起来不错,但这就是我提出这个问题的原因:我不知道它是否合适。我的猜测是,有更好的方法来滑动对象,而不是在途中手动定义100个点,并使用此动画将对象移动到每个点。

1 个答案:

答案 0 :(得分:1)

这可行,但不是偏移元素的理想方式。为什么?因为当你真正需要一个 DiscreteObjectKeyFrame时,你创建了两个DoubleAnimation

您几乎不应该为元素的Margin设置动画。要改变其位置,更好的方法是为其变换(TranslateX)的转换值(即TranslateY / RenderTransform)设置动画。

在变换中动画任何内容都是有效的。它们不在UI线程中。传统上,它们运行在一个名为 Compositor 线程的特殊线程中(我认为),但自从 Creators Update 以来,它们根据{{3}变得更加高效。 } -

  

当你在XAML中使用Storyboard和Transition动画时,你就是   使用引擎盖下的组合物。动画以每帧60帧的速度运行   第二!

以下是使用此类技术的示例

public static void Slide(this UIElement target, Orientation orientation, double? from, double to, int duration = 400, int startTime = 0, EasingFunctionBase easing = null)
{
    if (easing == null)
    {
        easing = new ExponentialEase();
    }

    var transform = target.RenderTransform as CompositeTransform;
    if (transform == null)
    {
        transform = new CompositeTransform();
        target.RenderTransform = transform;
    }
    target.RenderTransformOrigin = new Point(0.5, 0.5);

    var db = new DoubleAnimation
    {
        To = to,
        From = from,
        EasingFunction = easing,
        Duration = TimeSpan.FromMilliseconds(duration)
    };
    Storyboard.SetTarget(db, target);
    var axis = orientation == Orientation.Horizontal ? "X" : "Y";
    Storyboard.SetTargetProperty(db, $"(UIElement.RenderTransform).(CompositeTransform.Translate{axis})");

    var sb = new Storyboard
    {
        BeginTime = TimeSpan.FromMilliseconds(startTime)
    };

    sb.Children.Add(db);
    sb.Begin();
}

请注意,由于新的Composition API,在UWP中有更强大的动画支持。但是,合成中的偏移动画可能有点Windows UI team

然而, UWP社区Tookit 在包装BlurOffset等有用的动画方面做得非常出色。请随时查看tricky