【Win 10 应用开发】UI Composition 札记(三):与 XAML 集成

2021-04-30 21:28

阅读:628

标签:nba   作用   sprite   原来   target   集合   host   并且   nta   

除了 DirectX 游戏开发,我们一般很少单独使用 UI Composition ,因此,与 XAML 互动并集成是必然结果。这样能够把两者的优势混合使用,让UI布局能够更灵活。

说到与 XAML 的集成,则我们必须先认识一位伙计,他非常重要,位于 Windows.UI.Xaml.Hosting 命名空间下,名叫 ElementCompositionPreview ,有了它,我们才可以在 XAML 元素与 Composition UI 元素之间游走。来看看它都公开了哪些成员。

    public sealed class ElementCompositionPreview : IElementCompositionPreview
    {

        public static void SetImplicitShowAnimation(UIElement element, ICompositionAnimationBase animation);

        public static void SetImplicitHideAnimation(UIElement element, ICompositionAnimationBase animation);

        public static void SetIsTranslationEnabled(UIElement element, bool value);

        public static CompositionPropertySet GetPointerPositionPropertySet(UIElement targetElement);

        public static Visual GetElementVisual(UIElement element);

        public static Visual GetElementChildVisual(UIElement element);

        public static void SetElementChildVisual(UIElement element, Visual visual);

        public static CompositionPropertySet GetScrollViewerManipulationPropertySet(ScrollViewer scrollViewer);
    }

这个类公开的方法都是静态的,无需实例调用。我们不要急于弄懂每个方法的作用,这样会把自己带入死胡同。此处,我们先重点掌握以下几个方法的用法。

1、GetElementVisual:要使 XAML 元素与 Composition API 交互,这个方法特别要紧,通过调用它,我们可以得到 XAML 元素中的 Composition UI 树的表示元素,并且能获取到关联的 Compositor 对象,有了关联的 Compositor实例,我们才能创建各种 UI 元素。

2、SetElementChildVisual:当我们使用 Composition API 创建完自定义的 UI 元素后,要调用这个方法把它插入到 XAML 对象的可视化树中。注意,UI 元素总是被插入到可视化树的最后一个位置,因此,我们自己组装的元素总是会挡住原来的 XAML 元素的。这个你得注意。

3、GetElementChildVisual:只有你调用过 SetElementChildVisual 方法把自定义 Visual 元素加入过可视化树,才能调用这个方法,这个方法就是返回你上一次插入的元素。如果你没有插入过自定义的可视化元素,则该方法会返回 null。注意,不要把这个方法跟 GetElementVisual 方法混淆,两者不同。GetElementVisual 方法是获得与目标 XAML 对象关联的可视化对象,而 GetElementChildVisual 方法是获取你上一次插入到可视化树的自定义元素。

 

下面给大伙看一个例子。

在页面上,我放了一个 Border 对象。

    Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        Border Name="bd" Background="Black"/>
    Grid>

顺便把它的背景设置为黑色,方便后面看电影。

 

切换到代码文件,现在我们自定义组装一下UI,然后插入到 Border 元素的子树中。

        public MainPage()
        {
            this.InitializeComponent();
            CompositMyVisual();
        }


        void CompositMyVisual()
        {
            Visual visualForbd = ElementCompositionPreview.GetElementVisual(bd);
            // 组建UI
            Compositor compos = visualForbd.Compositor;
            // 根元素
            ContainerVisual rootvs = compos.CreateContainerVisual();
            // 第一个可视化元素
            SpriteVisual v1 = compos.CreateSpriteVisual();
            v1.Brush = compos.CreateColorBrush(Colors.Green);
            v1.Size = new Vector2(450f, 300f); //大小
            v1.Offset = new Vector3(30f, 20f, -1f); //位移
            rootvs.Children.InsertAtTop(v1);
            // 第二个可视化元素
            SpriteVisual v2 = compos.CreateSpriteVisual();
            v2.Brush = compos.CreateColorBrush(Colors.SkyBlue);
            v2.Size = new Vector2(400f, 400f);
            v2.Offset = new Vector3(180f, 125f, 0f);
            rootvs.Children.InsertAtTop(v2);

            // 这一句很重要
            ElementCompositionPreview.SetElementChildVisual(bd, rootvs);
        }

记得,在组装完UI元素后,要调用 ElementCompositionPreview.SetElementChildVisual方法,把自定义的元素插入到可视化树中。

在前面的博文中,老周介绍过,ContainerVisual 是个容器元素,它公开一个 Children 集合,我们可以向其中添加子元素,这里头有四个方法我们可以调用。

1、InsertAtTop :子元素会始终位于其他元素的顶部,所以这个元素会遮挡住其他元素。

2、InsertAtBottom:所添加的子元素始终在显示层的底部,它会被其他元素遮挡。

3、InsertAbove:把当前子元素放到某个元素之上。比如我们可以明确指定让当前元素位于 A 元素之上,这使得当前元素可能遮挡住 A 元素。

4、InsertBelow:把当前元素放到某个元素的下方。如果当前元素放在 A 元素下面,那么,该元素可能被 A 元素遮挡。

 

我们看看这个例子的效果。

技术分享

 

 在上面的代码中,第一个元素是绿色画刷填充的,第二个是天蓝色的,而我们在插入元素树时,都把它们放到所有元素的顶部。

    rootvs.Children.InsertAtTop(v1);
    rootvs.Children.InsertAtTop(v2);

都位于顶部,那么后加上去的元素就会挡住前面的元素,所以我们看到,天蓝色的那块区域挡住了绿色区域的一部分。

 

使用这种交互,我们还可以很轻松地对 XAML 元素进行三维旋转。

这个例子的界面分为两部分。左边咱们放三个滑块,分别调节 XAML 对象在 X、Y、Z 轴上的旋转角度,范围在 -90 到 90 之间。

            Slider Name="sldX" Header="X 轴" Maximum="90" Minimum="-90" SmallChange="1" StepFrequency="1" Value="0" ValueChanged="OnSliderValChanged"/>
            Slider Name="sldY" Header="Y 轴" Maximum="90" Minimum="-90" SmallChange="1" StepFrequency="1" Value="0" ValueChanged="OnSliderValChanged"/>
            Slider Name="sldZ" Header="Z 轴" Maximum="90" Minimum="-90" SmallChange="1" StepFrequency="1" Value="0" ValueChanged="OnSliderValChanged"/>

界面的右边是一个矩形。

  Rectangle Grid.Column="1" Width="300" Height="300" Fill="Brown" Name="rect"/>

我们就是要让这个矩形进行三维旋转。

定义一个方法,从以上三个 Slider 控件中获得实时的值,然后改变矩形的三维方向(在三个轴上的旋转角度)。

        void SetUI()
        {
            Visual v = ElementCompositionPreview.GetElementVisual(rect);
            // 设置方向
            float x = (float)sldX.Value;
            float y = (float)sldY.Value;
            float z = (float)sldZ.Value;
            Quaternion q = new Quaternion(x, y, z, 1f);
            v.Orientation = q;
        }

一个 Quaternion 实例包含四个值,前三个就是三个坐标轴上旋转的值,那个 W 不管它,始终给它分配 1 就行了。

 

来,看看效果。

技术分享

 

这个示例的源代码可以 点击这里下载。

 

好,本篇咱们就聊到这里,下一篇老周再介绍一下如何用 Win 2D 组件在 XAML 元素上画点东东,可以实现 WPF 中自定义 Renderer 的效果。

 

【Win 10 应用开发】UI Composition 札记(三):与 XAML 集成

标签:nba   作用   sprite   原来   target   集合   host   并且   nta   

原文地址:http://www.cnblogs.com/tcjiaan/p/7798041.html


评论


亲,登录后才可以留言!