第3章 Java UI 应用开发中,界面设计和UI布局是必不可少的。任何一个应用都需要在屏幕上显示用户界面,包含用户可查看并与之交互的所有内容。在HarmonyOS中,可通过Java和JS两种方式布局UI。本章先讲述Java UI布局,在第5章将讲述JS UI布局。 在学习使用Java对UI进行设计之前,首先需要理解一下HarmonyOS的UI逻辑。依据功能和特点,可将HarmonyOS的UI组件分为两类: 单体组件Component和可用于装载其他组件的容器组件ComponentContainer。 UI组件根据一定的层级结构进行组合形成整体的UI。单体组件在未被添加到容器组件中时,既无法显示也无法交互,因此一个用户界面至少包含一个容器组件。此外,容器组件中不但可以添加单体组件,也可以添加其他的容器组件,这样就可以形成丰富多样的UI样式。HarmonyOS的UI视图树范例如图3.1所示。 图3.1HarmonyOS的UI视图树范例 单体组件和容器组件以树状的层级结构进行组织,这样的布局被称为视图树。视图树的特点是仅有一个根视图,其他视图有且仅有一个父节点,视图之间的关系受到父节点的规则约束。 3.1Java UI单体组件 本章主要讲解使用Java语言设置单体UI组件。 HarmonyOS常用的单体UI组件全部继承自Component类,Component类包含了对UI组件的全部常用方法,例如创建、更新、缩放、旋转及设置各类事件监听器。其他的UI组件,如Text、Button等,都是在Component类的基础上添加了对应的功能实现的。以下是常用单体组件的开发流程。 3.1.1Text组件 Text是用来显示字符串的组件,是应用开发中最基础的组件,在界面上显示为一块文本区域。下面学习Text的用法。 1. Java代码创建Text组件 首先按照第1章的介绍,创建一个Phone设备的Java模板,用来学习使用代码创建UI布局。在新建项目中的界面左侧找到Project项目栏,双击打开entry→src→main→项目Package名称(本书中为com.huawei.mytestapp)→Slice中的MainAbilitySlice.java文件,如图3.2所示。 图3.2MainAbilitySlice文件路径 在打开后的Java文件中找到onStart()方法,修改其中的内容,代码如下: //MainAbilitySlice.java public void onStart(Intent intent) { super.onStart(intent); //容器 DirectionalLayout myLayout = new DirectionalLayout(this); myLayout.setWidth(DirectionalLayout.LayoutConfig.MATCH_PARENT); myLayout.setHeight(DirectionalLayout.LayoutConfig.MATCH_PARENT); myLayout.setAlignment(LayoutAlignment.HORIZONTAL_CENTER); myLayout.setPadding(32,32,32,32); //Text组件 Text text = new Text(this); text.setWidth(DirectionalLayout.LayoutConfig.MATCH_CONTENT); text.setHeight(DirectionalLayout.LayoutConfig.MATCH_CONTENT); text.setText("My name is Text."); text.setTextSize(24, Text.TextSizeType.VP); myLayout.addComponent(text); super.setUIContent(myLayout); } 下面对代码的具体内容进行讲解。 图3.3Text组件的 运行效果 第一个代码块对容器组件进行了设置,页面容器组件的相关说明会在下一节中进行。第二个代码块设置并添加了一个Text组件,其中前5行代码创建并设置了一个Text组件,每一句的具体意义如下: 第1行: 实例化一个Text类的实例,实例名为text。 第2和第3行: 为text设置了宽和高属性,这样可以让组件的大小自动适配其内容(文本)的大小。 第4行: 为text添加要显示的文字信息My name is Text。 第5行: 为text的文本字体设置大小24vp。 至此,text的属性就设置完毕了,为了使text能够在手机屏幕上显示,还需要执行super.setUIContent(myLayout),将创建好的Text组件实例text放入容器组件中,相关知识在后面讲到容器组件时会具体说明。运行上述代码,效果如图3.3所示。 从图3.3可以看出,页面顶部出现了一条黑色的文本信息,显示My name is Text,说明上述设置均已生效。 还可以使用Java代码修改或添加一些属性,例如,使用setTextColor()方法可以修改text的字体颜色,使用setFont()方法可以修改text的字体。在Text组件代码块中添加代码如下: //MainAbilitySlice.java中的Text组件 Text text = new Text(this); text.setWidth(DirectionalLayout.LayoutConfig.MATCH_CONTENT); text.setHeight(DirectionalLayout.LayoutConfig.MATCH_CONTENT); text.setText("My name is Text."); text.setTextSize(24, Text.TextSizeType.VP); text.setTextColor(Color.BLUE); text.setFont(Font.DEFAULT_BOLD); myLayout.addComponent(text); 上述代码将text的文本设置为蓝色,字体加粗。重新运行程序,运行结果如图3.4所示。 2. xml创建Text组件 在实际应用中,为了代码的简洁美观,通常会使用xml进行布局,这里学习通过xml进行UI布局,实现相同的效果。在界面左侧的Project项目栏选择entry→src→main→resources→base→layout,打开ability_main.xml,如图3.5所示。 图3.4Text组件的属性设置效果 图3.5xml布局目录结构 打开ability_main.xml文件,对布局和组件进行描述,代码如下: 其中,最外层的DirectionalLayout指页面的整体竖向布局。在Text中,使用ohos:id为当前控件定义一个唯一的标识id,布局中的组件通常都需要设置独立的id,以便在程序中查找该组件。若布局中有不同的组件设置了相同的id,则通过id查找会返回查找到的第一个组件,因此尽可能保证id的唯一性。使用ohos:width和ohos:height为控件指定了宽度和高度,其属性值match_parent表示组件大小将扩展为父容器允许的最大值,占据父组件方向上的剩余大小,即由父组件决定当前控件的大小。属性值match_content表示组件大小与它的内容占据的大小范围相适应,即由控件内容决定当前控件的大小。除此之外也可以通过具体的数值设置宽和高,例如24(以像素为单位)或24vp(以屏幕相对像素为单位)。使用ohos:layout_alignment指定文字的对齐方式,其中horizontal_center指水平方向居中。通过ohos:text设置Text的具体内容。 随后,在MainAbilitySlice.java中,注释掉通过Java创建Text组件的代码,并通过setUIContent()加载该xml布局。修改MainAbilitySlice.java中的代码如下: //MainAbilitySlice.java public class MainAbilitySlice extends AbilitySlice { @Override public void onStart(Intent intent) { super.onStart(intent); …//注释通过Java创建Text组件代码 super.setUIContent(ResourceTable.Layout_ability_main); //加载xml布局 } } 现在运行程序,效果如图3.6所示。 在xml中也可以对Text设置字体颜色及字重。在ability_main.xml中,增加属性代码如下: 通过ohos:text_color属性可以设置文本的颜色,通过ohos:text_weight属性可以设置文本的字重。重新运行后效果如图3.7所示,可见text文本变为蓝色,且字体加粗。 图3.6xml创建Text组件的运行效果 图3.7xml中设置Text颜色及字重运行效果 除此之外,Text还有很多其他的属性,在开发过程中根据需求查阅相关文档即可。 3.1.2Button组件 Button(按钮)是一种常见的与用户进行交互的组件,单击可以触发对应的操作,可以由图标和文本共同组成。 1. Java代码创建Button组件 同样地,还是先尝试使用Java代码来添加一个Button组件。打开MainAbilitySlice.java,在onStart()函数中添加如下代码: //MainAbilitySlice.java中添加Button组件 Button button = new Button(this); button.setWidth(DirectionalLayout.LayoutConfig.MATCH_PARENT); button.setHeight(DirectionalLayout.LayoutConfig.MATCH_CONTENT); button.setText("button"); button.setTextSize(28, Text.TextSizeType.VP); ShapeElement backgroundElement = new ShapeElement(); backgroundElement.setRgbColor(new RgbColor(0xDC,0xDC,0xDC)); button.setBackground(backgroundElement); myLayout.addComponent(button); 值得注意的是,此时如果直接运行程序会发现UI界面没有变化,这是因为在3.1.1节最后使用了setUIContent()加载了xml布局ability_main.xml,而修改的代码是创建的布局myLayout,这是两套互不干涉的布局,所以如果想看到刚刚在代码布局中添加的button,需要将setUIContent()函数中的变量改为myLayout,然后运行程序,这样就可以看到的text下方多出了button。Button组件也有丰富的自定义属性,大家同样可以根据自己的需求来查阅相关文档。 2. 使用xml创建Button组件 同样也可以使用xml来添加Button组件,在刚才编写的ability_main.xml文件中增加Button,代码如下: //ability_main.xml ...