C#UWP中的滑动元素 [英] Sliding elements in c# UWP

查看:109
本文介绍了C#UWP中的滑动元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对UWP中的动画有疑问。我想在应用程序的底部有一个菜单,然后在顶部点击该菜单,即可向上(显示)或向下(几乎完全隐藏)滑动。我之前在学习WPF,在那里我知道可以使用ThicknessAnimation移动控件的边距并使它滑动。不幸的是,在UWP中,我无法使用ThicknessAnimations,因此我尝试寻找另一种方法。我希望它可以为任意FrameworkElement工作(以便能够重用它)。最终,我想出了以下解决方案:

I have a question about animations in UWP. I want to have a menu on the bottom of my app that, when tapped on the top, slides up (shows) or down (hides almost entirely). I was learning WPF before and there I know I can use ThicknessAnimation to move the margin of my control and have it slide. Unfortunately, in UWP I can't use ThicknessAnimations, so I tried to find another way. I want this to work for an arbitrary FrameworkElement (so as to be able to reuse it). Eventually, I came up with this solution:

    /// <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个点并使用此动画将对象移动到每个点。

It works, looks nice, but here's the reason I'm asking this question: I don't know if it's proper. My guees is that there's a better way to slide objects than manually define 100 points on the way and move the object to each point using this animation.

推荐答案

这有效,但不是抵消元素的理想方法。为什么?因为当您实际上只需要一个 DoubleAnimation 时,就创建了两个 DiscreteObjectKeyFrame

This works but is just not the ideal way to offset an element. Why? Because you are creating two many DiscreteObjectKeyFrames when you really just need one DoubleAnimation.

几乎应该永远不要为元素的 Margin 设置动画。要更改其位置,一种更好的方法是对其转换的转换值(即 TranslateX / TranslateY )进行动画处理( RenderTransform )。

You should almost never animate the Margin of an element. To change its position, a better approach is to animate the translate values (i.e. TranslateX/TranslateY) of its transform (RenderTransform) instead.

对转换中的任何内容进行动画处理是有效的。它们不在UI线程中。传统上,它们在称为 Compositor 的特殊线程中运行(我认为),但是自 Creators Update 以来,根据 Windows用户界面团队-

Animating anything in transform is efficient. They are off the UI thread. Traditionally, they were running in a special thread called Compositor thread (I think), but ever since the Creators Update, they have become even more performant according to the Windows UI team -


当您在XAML中使用Storyboard和Transition动画时,使用幕后的Composition可以使您获得
的收益。动画以每秒
每秒60帧的速度运行!

When you use Storyboard and Transition animations in XAML, you’re using Composition under the hood. Animations run at 60 frames per second!

以下是使用这种技术的示例

The following is an example of using such technique

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

请注意,由于这种方法具有较高的性能,因此在其中提供了更强大的动画支持UWP,得益于新的Composition API。但是合成中的偏移动画可能有点 tricky

Note as performant as this approach gets, there is even more powerful animation support in UWP, thanks to the new Composition API. But offset animation in Composition can be a bit tricky.

但是, UWP社区Tookit 做得很好,包裹了一些有用的动画,例如 Blur 偏移量等。请随时检查 them 退出。

However, the UWP Community Tookit has done a great job wrapping some useful animations like Blur, Offset, etc. Feel free to check them out.

这篇关于C#UWP中的滑动元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆