【Win 10 应用开发】UI Composition 札记(二):基本构件
在上一篇中,老周用一个示例,演示了框架视图的创建过程,在本篇中,老周将给大伙伴们说一下 Composition 构建 UI 的一些“零件”。
UI Composition 有一个核心类——对,就是 Compositor 类,它是总生产车间,组成 UI 的各种元素都可以由它来创建,所以,你会看到,它公开了 K 个以 Create 开头的方法。我们在组建 UI 时所用到的各种元素都可以调用这些以 Create 打头的方法来创建。
要让用户在窗口上看到你所构建的 UI 元素,可视化树中至少需要一 Visual 对象。Visual 是一个基类,在组成可视化树时,我们有三种 Visual 可以用。
第一种是 ContainerVisual,它表示一容器,可以向它的 Children 集合中添加子元素,以构建复杂的可视化对象。
第二种是 SpriteVisual,它从 ContainerVisual 类派生,所以也支持添加子元素。Sprite 是“小仙女”的意思,表明这个类不仅仅是个容器,它自身就可以绘制可视化内容,所以这个类用得还是比较多的。它主要公开了 Brush 属性,可以使用各种画刷来绘制内容。比如,单种颜色填充的画刷,渐变画刷,绘制图形的画刷等。
第三种是 LayerVisual,它也是容器元素,它类似于在视图中创建一个图层,并可以在其中继续添加子元素。
要呈现多彩灿烂的内容,你需要画刷,因此,UI Compositon 提供各种用途的画刷。
1、单色画刷,只有一种颜色对对定可视化元素进行填充。
2、渐变画刷,可以设置多种颜色过度。
3、Drawing Surface ,这个强大,相当于一块自由画布,你可以在上面画各种东东。你可以画文本,画圆形,画线,画大象,画野鸭子。甚至你可以在上面画一个正在播放的视频。绘制代码是要用C++来写,不过我们可以结合 Win 2D 组件一起用,这个老周后面会绘出例子的。
4、效果画刷。这种画刷主要用来产生一些视觉效果,比如模糊、锐化、颜色叠加、反相等等。
有了可视化对象和画刷,我们基本上可以弄出很多东西来。不过,可能大伙伴们会想了,要是能模拟一些真实场景就更佳了。于是,灯光就出场了。灯光就是模拟我们现实世界中的各种光源,比如小灯泡发出的点光,手电筒照射的光,或者照射范围更大的环境光(如白炽灯)等。
1、SpotLight,这种光源有点像手电筒的光,发散出去后会产生一个锥形区域。
2、PointLight,类似于一盏小灯泡,光源是一个点,但它可以向四周照射。
3、DistantLight,这种光有点像汽车的远光灯(晚上开车时别乱开远光啊,会害死人的),也像太阳光。总之,这种光源照射面很大,而且光很强,传播距离远。
4、AmbientLight,这种光就像你家里,房间里安装的白炽灯,或者是新型的节能灯,白白的光,可以照亮整个屋子,即环境光。
老周这么一说,你一定会觉得没意思,都不知道灯光照起来是什么效果。别急,老周后面会给例子的,你会看到效果的。
有刷子,有灯泡,有画布,你大概觉得差不多了,可以画出很多大作了。是的,不过,要是你的大作能够动起来,是不是更生动了呢。比如你画了猪八戒,手里拿着个大西瓜,要是能让八戒动起来,尤其是嘴巴,一下一下地啃西瓜皮,那该多好。因此,你还需要动画。
1、关键帧动画。这个应该好懂,就是可以在某个时刻设置一个关键帧,然后关键帧之间会自动以时间为基准产生过度动画。
2、表达式。即使用一个计算公式来生成动画所需要的值。比如你要对可视化元素的不透明度进行动画处理,输入 Opacity * 0.5,表示每次的不透明度变化,最终值都是上一次计算结果的一半,比如,不透明度为 100%,进行动画后变成 50%,再进行一次动画后就成 25% …… 要注意的是,表达式产生的动画是不能控制时间的。
以上内容你不必太认真看,就当作常识,大致涉猎一下就 OK 了,后续的博文中,老周会逐个介绍的。接下来,我们要了解一下如何构建 UI 树。
咱们一起来动动手,学习编程一定要动手的(当然,动脑子是必须的),如果你能用脚打字,也可以动脚。
记得老周一一篇中说过的吧,我们要先实现自己的一个视图,即实现 IFrameworkView 接口。
class DemoView : IFrameworkView
{
……
}
然后,我们声明几个私有字段。
Compositor mCompositor = null;
CoreWindow mWindow = null;
SpriteVisual rootVisual = null;
要组装 UI 构件,我们需要一个 Compositor 类的实例,在这个例子中,我打算用 SpriteVisual 作为 UI 树的根,它既可以用画刷绘制内容,也可以添加子元素,正可谓是一物两用。
接着,进行初始化,此时我们可以实例化 Compositor 对象,或者实例化其他我们需要的东西。注意此时不要组建 UI 树,因为窗口还未初始化,此时建UI树会发生异常。
public void Initialize(CoreApplicationView applicationView)
{
mCompositor = new Compositor();
}
Load方法我们这里没啥要加载的,就留空吧。
public void Load(string entryPoint)
{
// 留着以后用来养金鱼
}
接下来是重点,SetWindow 方法,此时窗口已经可用,所以此时可以组建 UI 树了。
public void SetWindow(CoreWindow window)
{
mWindow = window;
// 创建根元素
rootVisual = mCompositor.CreateSpriteVisual(); // 这个是重点,必须要有这个 target
CompositionTarget target = mCompositor.CreateTargetForCurrentView();
// 指定 UI 根元素
target.Root = rootVisual; // 这时候UI元素上是空白的
// 为了能看到东西,我们画点东西上去
CompositionColorBrush backBrush = mCompositor.CreateColorBrush(Colors.Blue);
rootVisual.Brush = backBrush;
}
这里有一个很重要的东东,大伙要严重注意。在组建 UI 时,你必须调用 CreateTargetForCurrentView 方法创建一个 CompositionTarget 实例,它直接与当前的应用程序视图关联的,你必须创建一个该实例,然后再把 UI 的根元素赋值给 CompositionTarget 的 Root 属性。Root 属性引用的UI元素就作为整个视图的根。
而且,这个 target 在整个视图的生命周期内,你只能创建一次,如果设置了根元素后,你还调用 CreateTargetForCurrentView 方法的话,你会收到一条 DCOMPOSITION_ERROR_WINDOW_ALREADY_COMPOSED 错误,该错误提醒你,该可视化树已经组装过了,你不能再调用了。
CreateColorBrush 方法创建一个单色填充的画刷,这里我用的是蓝色。
在 Run 方法中开启消息循环。
public void Run()
{
mWindow.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessUntilQuit);
}
但是,以上代码漏了一句,所以一旦运行,你只能看到初始屏幕。如下图。

因为你还没有激活当前窗口,故你在 ProcessEvents 之前,要加上这一句。
public void Run()
{
mWindow.Activate();
mWindow.Dispatcher.ProcessEvents(CoreProcessEventsOption.ProcessUntilQuit);
}
因为我用 mWindow 字段引用了当前窗口的实例(就是刚刚上面的 SetWindow 方法中),所以我直接调用 Activate 方法。如果你没有用变量存储当前窗口的实例,你还可以这样调用。
CoreWindow.GetForCurrentThread().Activate();
最后,在视图销毁时,打扫一下卫生。
public void Uninitialize()
{
rootVisual.Dispose();
mCompositor.Dispose();
mWindow = null;
}
视图的逻辑弄完了,再实现一下 IFrameworkViewSource 接口。
class DemoViewSource : IFrameworkViewSource
{
public IFrameworkView CreateView()
{
return new DemoView();
}
}
别忘了入口点。
class Program
{
static void Main()
{
CoreApplication.Run(new DemoViewSource());
}
}
好,大功告成!按下【F5】键,你满怀信心地看着程序启动。结果傻眼了,FK!怎么一片空白的?

咋回事呢?是啊,咋回事呢。再检查一下代码,逻辑都对啊。其实,你之所以看不到东西,是因为可视化元素的大小默认是 0,所以,你要回到 SetWindow 方法,给可视化元素设一个 Size。
public void SetWindow(CoreWindow window)
{
mWindow = window;
// 创建根元素
rootVisual = mCompositor.CreateSpriteVisual();
rootVisual.Size = new System.Numerics.Vector2(300f, 320f);
……
}
如果必要,你还可以设置视图对象的偏移量,默认是 0、0、0,即位于窗口的左上角,注意这个坐标是三个值的,即XYZ三个轴,X和Y轴你都懂的,原点在左上角,X轴正方向往右,Y轴正方向往下。至于Z轴嘛,从屏幕里面向外,说白了就是正方向指着你。
可以设置一下偏移量。
public void SetWindow(CoreWindow window)
{
mWindow = window;
// 创建根元素
rootVisual = mCompositor.CreateSpriteVisual();
rootVisual.Size = new System.Numerics.Vector2(300f, 320f);
rootVisual.Offset = new System.Numerics.Vector3(0f, 20f, 5f);
……
}
好了,一切的疑问都解开了。再运行一下,Good,效果出来了。

其实,你还可以让它带透明效果的,方法和 XAML 中一样。
public void SetWindow(CoreWindow window)
{
……
rootVisual = mCompositor.CreateSpriteVisual();
rootVisual.Size = new System.Numerics.Vector2(300f, 320f);
rootVisual.Offset = new System.Numerics.Vector3(0f, 20f, 5f);
rootVisual.Opacity = 0.5f;
……
}
再看看效果。

有趣吧,你还可以对它进行旋转的。
rootVisual.RotationAngleInDegrees = 60f;
RotationAngle 属性设置的旋转角度是弧度角,要用角度进行设置,就用 RotationAngleInDegrees 属性。
你不过瘾的话,还可以调整整个三维坐标的方向。
rootVisual.Orientation = new System.Numerics.Quaternion(-15f, 5f, 2f, 1f);
然后就变成这个样子了。

怎么样,有意思吧。本篇就扯到这里,大伙伴只要知道UI元素的组装方法就可以了,至于说那些三维变量如何设置,这个可以网上查资料,或者自己摸索,三维方面的东西还是挺复杂,其实老周也不是很了解,写出来大家交流交流而已。
【Win 10 应用开发】UI Composition 札记(二):基本构件的更多相关文章
- 【Win 10 应用开发】UI Composition 札记(一):视图框架的实现
在开始今天的内容之前,老周先说一个问题,这个问题记得以前有人提过的. 设置 Windows.ApplicationModel.Core.CoreApplicationView.TitleBar.Ext ...
- 【Win 10 应用开发】UI Composition 札记(三):与 XAML 集成
除了 DirectX 游戏开发,我们一般很少单独使用 UI Composition ,因此,与 XAML 互动并集成是必然结果.这样能够把两者的优势混合使用,让UI布局能够更灵活. 说到与 XAML ...
- 【Win 10 应用开发】UI Composition 札记(四):绘制图形
使用 Win 2D 组件,就可以很轻松地绘制各种图形,哪怕你没有 D2D 相关基础,也不必写很复杂的 C++ 代码. 先来说说如何获取 Win 2D 组件.很简单,创建 UWP 应用项目后,你打开“解 ...
- 【Win 10 应用开发】UI Composition 札记(五):灯光
UI Composition 除了能够为 UI 元素建立三维空间外,还有相当重要的一个部件——灯光.宇宙万物的精彩缤纷,皆源于光明,光,使我们看到各种东西,除了黑洞之外的世界都是五彩斑谰的.故而,真要 ...
- 【Win 10 应用开发】UI Composition 札记(六):动画
动画在 XAML 中也有,而且基本上与 WPF 中的用法一样.不过,在 UWP 中,动画还有一种表现方式—— 通过 UI Composition 来创建. 基于 UI Composition 的动画, ...
- 【Win 10 应用开发】启动远程设备上的应用
这个功能必须在“红石-1”(build 14393)以上的系统版中才能使用,运行在一台设备上的应用,可以通过URI来启动另一台设备上的应用.激活远程应用需要以下前提: 系统必须是build 14393 ...
- 【Win 10应用开发】Adaptive磁贴模板的XML文档结构
在若干天之前,老周给大家讲了Adaptive Toast通知的XML模板,所以相应地,今天老周给大家介绍一下Adaptive磁贴的新XML模板. 同样道理,你依旧可以使用8.1时候的磁贴模板,在win ...
- 【Win 10应用开发】认识一下UAP项目
Windows 10 SDK预览版需要10030以上版本号的Win 10预览版系统才能使用.之前我安装的9926的系统,然后安装VS 2015 CTP 6,再装Win 10 SDK,但是在新建项目后, ...
- 【Win 10 应用开发】在代码中加载文本资源
记得前一次,老周给大伙,不,小伙伴们介绍了如何填写 .resw 文件,并且在 XAML 中使用 x:Uid 标记来加载.也顺便给大伙儿分析了运行时是如何解析 .resw 文件的. 本来说好了,后续老周 ...
随机推荐
- HTML5基本标签的使用
第一次写这种东西,肯定存在许多不足之处,还望大家多多担待,我会继续加油的!我也是一名HTML5的初学者,只是将这几周在课堂上所听到的东西分享给大家. 下面给大家介绍一下H5! 一.<!DOCTY ...
- css左右布局的几种实现方式和优缺点
记录一下左右布局的实现方式,实现的具体效果是,左侧固定宽度,高度适中等于父元素的高度,父元素的高度由右侧内容决定: html代码如下: <div class="parent" ...
- java 面向对象 2
一.JAVA类的定义 JAVA里面有class关键字定义一个类,后面加上自定义的类名即可.如这里定义的person类,使用class person定义了一个person类,然后在person这个类的类 ...
- Instance of 的用法
来自:百度百科 instanceof主要用于判断是否是某个类的实例 任何的对象都可以调用 返回结果是Boolean型数值Class AA a=new A();boolean b=a instanceo ...
- Django内置的用户认证
认证登陆 在进行用户登陆验证的时候,如果是自己写代码,就必须要先查询数据库,看用户输入的用户名是否存在于数据库中: 如果用户存在于数据库中,然后再验证用户输入的密码,这样一来就要自己编写大量的代码. ...
- postman - 基本操作
设置环境 collections 导入 runner 导入 api 配置api 编写测试(请求和响应)脚本 api的保存和导出 setting file -- setting
- zoj 1081 Points Within (判断点是否在多边形内)
http://blog.csdn.net/zxy_snow/article/details/6339621先保存,搞懂了再来写
- Win10系统下安装Ubuntu16.04.3教程与设置
在Win10上刚刚装好Ubuntu16.04.3,装了不下于10次,期间出现很多问题,趁着还有记忆,写下这篇教程,里面还有Ubuntu系统的优化与Win10的一些设置. Part 1 制作Ubuntu ...
- win10 uwp App-to-app communication 应用通信
这篇文章都是乱说的,如果觉得有不好的,可以发我邮箱 应用之间需要相互的发送信息,就是我们经常用的分享 有个人看到一个网页很好,于是就希望把这个网页发送到邮件,那么这样的话就是使用应用通信. 因为每个应 ...
- Java 线程基本知识
线程 线程和进程 进程 : 进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 线程 : 线程是进程中的一个执行单元(执行路径 ...