【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 文件的. 本来说好了,后续老周 ...
随机推荐
- 插入排序-python实现
def insert_sort(arr): for j in range(1,len(arr)): #从list第二个元素开始 key=arr[j] ...
- 王者荣耀_KEY
WZRY 为了排位赛的Cjj神,最近耗尽气力来打WZRY. Cjj神最近有N局预约的排位赛,其中第i局需要耗时Li的时间.因为浓浓的Gay情,Cjj神不能改变这些排位赛的的顺序.作为一个很有(mei) ...
- jquery实现点击div外隐藏div
html <div style="width:100px;height:100px;border:1px solid #ff0" id="div"> ...
- jQuery: Callbacks
jQuery 中提供了一个Callback的工具类Callbacks,它提供了一个Callback Chain.使用它可以在一个chain上来执行相关操作.它也是jQuery中的ajax, Defer ...
- VPS修改SSH端口不小心把自己给墙掉的一般解决办法
很多人配置服务器的时候都习惯将 SSH 端口改为其他端口,以规避批量端口扫描,但也有不少人改完端口却忘了去防火墙修改端口,导致 SSH 登陆不上. 昨天我就这么干了 我把SSH端口从22改成了2345 ...
- Java线程池详解
一.线程池初探 所谓线程池,就是将多个线程放在一个池子里面(所谓池化技术),然后需要线程的时候不是创建一个线程,而是从线程池里面获取一个可用的线程,然后执行我们的任务.线程池的关键在于它为我们管理了多 ...
- 1007 正整数分组 1010 只包含因子2 3 5的数 1014 X^2 Mod P 1024 矩阵中不重复的元素 1031 骨牌覆盖
1007 正整数分组 将一堆正整数分为2组,要求2组的和相差最小. 例如:1 2 3 4 5,将1 2 4分为1组,3 5分为1组,两组和相差1,是所有方案中相差最少的. Input 第1行:一个 ...
- Reshape the Matrix
In MATLAB, there is a very useful function called 'reshape', which can reshape a matrix into a new o ...
- 如何创建一个Django项目
Django 软件框架 软件框架是由其中的各个模块组成,每个模块负责特定的功能,模块与模块之间相互协作来完成软件开发. MVC简介 MVC框架的核心思想是:解耦,让不同的代码块之间降低耦合,增强代码的 ...
- javascript中DOM集锦(二)
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...