通过XML文件可以构建一个完整的用户界面,这个XML文件通常被称为布局文件。布局文件也属于应用资源的一类(详情可参见3.4.1节的相关内容),默认在HAP目录的/src/main/resources/base/layout中。例如,在HelloWorld工程中MainAbilitySlice的默认布局文件为ability_main.xml,如图3-4所示。
图3-4 布局文件ability_main.xml
接下来,让我们仔细看一看ability_main.xml文件,代码如下:
在上述代码中,根元素<DirectionalLayout>声明了一个定向布局。定向布局是将其内部的组件沿着一个方向(横向或纵向)依次排列的一种布局方式。这个定向布局处于根元素的位置,而根元素有一个重要的任务:定义命名空间,因此,该定向布局的xmlns:ohos属性定义了ohos的命名空间http://schemas.huawei.com/res/ohos。在各种布局和组件中,都应当使用ohos命令空间所定义的属性。例如,<DirectionalLayout>定向布局包含以下3个属性:
(1)ohos:height:组件(或布局)的高度。
(2)ohos:width:组件(或布局)的宽度。
(3)ohos:orientation:定向布局的组件排列方向:vertical表示纵向排列;horizontal表示横向排列。
组件(或布局)的高度和宽度属性可以通过以下几种类型进行定义,如图3-5所示。
(1)match_parent:由父布局或窗口对象决定组件的大小。通常,这个组件会填充整个父布局或整个窗口的大小。
(2)match_content:由组件的内容决定组件的大小。通常,这个组件会刚好包含组件中的内容。
(3)数值+px:通过像素值(pixel,px)规定组件大小。
(4)数值+vp:通过虚拟像素值(virtual pixel,vp)规定组件大小。关于像素与虚拟像素的概念和关系将在3.1.5节进行详细探讨。
图3-5 match_parent与match_content
在上面的定向布局中,由于<DirectionalLayout>是根元素,因此该布局为根布局,并且这个布局由应用程序的窗口对象管理。将定向布局的高度和宽度都设置为match_parent表示这个定向布局填充整个窗口对象。
注意: 窗口对象由ohos.agp.window.service.Window类定义。每个应用程序都包括了单例的窗口对象。通常情况下,应用程序的窗口是固定且占满整个屏幕的,但是,当设备处在分屏模式或者悬浮窗模式时,窗口的大小就不是全屏大小了,甚至是可以移动的。窗口对象可以通过Ability或AbilitySlice的getWindow()方法获取。
图3-6 窗口、定向布局和文本组件之间的关系
根元素<DirectionalLayout>包含了子元素<Text>,这说明这个定向布局包含了1个文本组件。在MainAbilitySlice中,窗口、定向布局和这个文本组件之间的关系如图3-6所示。
这个文本组件包含了以下属性:
· ohos:id:ID属性,用于唯一性的标识组件。
· ohos:height:组件高度,match_parent表示高度刚好填充整个父布局(定向布局)。
· ohos:width:组件宽度,match_content表示宽度刚好包含文字内容。
· ohos:background_element:背景元素。
· ohos:layout_alignment:布局对齐方式,horizontal_center表示水平居中。
· ohos:text:文本内容,设置为Hello World。
· ohos:text_size:文本大小,设置为50px。
注意: 如果读者查看过组件的说明文档,可以发现每个组件都含有包括AttrSet参数的构造方法。事实上,在应用程序运行时将XML布局中定义的组件转换为Java对象,而AttrSet参数用于接收XML定义组件时的各类属性。
文本组件的ID属性和背景要素都引用了工程的资源。资源通过资源引用字符串进行引用。通常,资源引用字符串的格式为$type:name,其中type表示资源类型,name表示资源名称。资源类型包括ID资源(id)、媒体资源(media)、布局资源(layout)、可绘制资源(graphic)等,其各类资源的详细说明详见3.4节。例如,在上面的文本组件中,背景元素属性为$graphic:background_ability_main,说明引用了名为background_ability_main的可绘制资源。
这些资源都会在ResourceTable类中自动生成一个静态类型常量的唯一标识符。通过这些标识符就可以在Java代码中获取相应的资源对象了。
唯一不同的是,ID资源需要在资源类型前加入“+”用以在ResourceTable类中自动生成该ID资源的唯一标识符。例如,在上面的文本组件中,ID属性为“$+id:text_helloworld”,此时就会在ResourceTable类中自动生成唯一标识符Id_text_helloworld常量。在引用这个ID属性时,就不需要“+”号了,使用“$id:text_helloworld”进行引用即可。
相应地,ability_main.xml这个文件作为布局资源,也在ResourceTable类中生成了对应的常量Layout_ability_main,因此,在AbilitySlice的onStart方法中,将这个常量作为参数传入setUIContent(int layoutRes)重载方法中即可实现布局资源(也即用户界面)的加载,即
注意: 如果在编程中提示没有找到ResourceTable类错误,或者该类中没有生成Layout_layout常量错误,则可以在Gradle工具窗体中执行entry→Tasks→ohos→generateDebugResources工具,此时可以重新生成ResourceTable类。
在DevEco Studio的Project工具窗体中,定位到HAP目录的/src/main/resources/base中,然后在base目录上右击,在弹出的菜单中选择New→Layout Resource File菜单,弹出创建布局资源对话框,如图3-7所示。
在File name选项中输入需要创建的布局名称layout;在Layout Type中选择布局的模板类型DirectionalLayout,即定向布局。单击Finish按钮,DevEco Studio会在layout目录中创建一个名为layout.xml的布局文件,并自动生成定向布局的基础代码,代码如下:
图3-7 创建布局资源文件
此时,开发者就可以根据需求和设计方案自定义布局中的内容了。由于这个布局文件属于应用资源,因此在ResourceTable类中会自动生成一个名为Layout_layout的标识符常量。在相应的AbilitySlice中,通过以下代码就可以使用该布局文件了。
通过XML文件构建用户界面有一个好处就是可以使用预览器(Previewer)实时预览用户界面的效果。
在代码编辑窗口中打开布局文件、Page源代码文件或AbilitySlice源代码文件的情况下,在DevEco Studio菜单栏中选择View→Tool Windows→Previewer菜单即可打开Previewer工具窗体,如图3-8所示。此时,这个窗体中显示了当前Page或当前AbilitySlice的预览界面。
注意: 通过这种方法也可以浏览JS UI中的HML界面。
在预览器的上方,有以下几个按钮和选项:
· 刷新(Refresh):刷新当前预览界面。
· 热刷新(ChangeHot):当打开该选项后,进行修改代码时会实时刷新预览界面。
· 多设备预览(Mult-idevice preview):当打开该选项后,可以同时显示该布局在多个设备上的预览界面。
· 缩小(Zoom Out):缩小预览界面。
· 放大(Zoom In):放大预览界面。
图3-8 通过预览器(Previewer)预览XML布局文件
另外,当单击预览界面下方的【...】按钮后,在弹出的Debugging下拉列表框中选中Screen coordinate system即可显示屏幕坐标系,便于分析各个组件的位置和大小是否符合设计规范。