版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第3章构建应用程序UI—基础UI,也就是UserInterface,或者称为用户界面,是用户与系统进行交互的桥梁。鸿蒙提供了完整的用于开发用户UI的技术架构,这个架构称为ArkUI框架,也称为方舟UI。本章ArkUI的基本使用进行介绍。目录3.1UI组件入门3.2系统内置UI组件介绍3.3资源分类与访问3.4细说UI3.5UI组件装饰器及其使用3.6渲染控制3.7案例:图来图往3.8练习:呼来唤去3.1UI组件入门在鸿蒙应用程序中,所有的用户UI都是一个自定义的UI组件。通过ArkUI提供的自定义组件机制,同时在自定义组件中使用ArkUI提供的组件,可以构建非常美观和灵活的用户界面。下面通过例子介绍如何构建用户界面。这个例子进行简单的算术运算:用户在两个输入框中分别输入两个数,然后点击代表不同运算方式的按钮,程序会按指定的运算方式对输入的数进行运算,然后将结果显示在第三个输入框中。完成后的程序的运行效果如图。下面介绍实现例子程序功能的代码。在DevEco中新建名称为Ch0301的程序工程。修改Index.ets代码为如下内容:@Entry@ComponentstructIndex{@Staten1:string='';@Staten2:string='';@Staten3:string='';
build(){Column(){TextInput({text:$$this.n1}).type(InputType.Number).id('n1').fontSize(30).fontWeight(FontWeight.Bold).margin({top:100,right:10,bottom:10,left:10}).borderWidth(2)
TextInput({text:$$this.n2}).type(InputType.Number).id('n2').fontSize(30).fontWeight(FontWeight.Bold).margin(10).borderWidth(2)
Row(){Button('+',{type:ButtonType.Capsule,stateEffect:true}).borderRadius(8).backgroundColor(0x317aff).fontSize(40).width(70).height(50).margin(10).onClick(()=>{letnum1:number=parseInt(this.n1);letnum2:number=parseInt(this.n2);letnum3:number=num1+num2;this.n3=String(num3);})Button('-',{type:ButtonType.Capsule,stateEffect:true}).borderRadius(8).backgroundColor(0x317aff).fontSize(40).width(70).height(50).margin(10).onClick(()=>{letnum1:number=parseInt(this.n1);letnum2:number=parseInt(this.n2);letnum3:number=num1-num2;this.n3=String(num3);})Button('*',{type:ButtonType.Capsule,stateEffect:true}).borderRadius(8).backgroundColor(0x317aff).fontSize(40).width(70).height(50).margin(10).onClick(()=>{letnum1:number=parseInt(this.n1);letnum2:number=parseInt(this.n2);letnum3:number=num1*num2;this.n3=String(num3);})Button('/',{type:ButtonType.Capsule,stateEffect:true}).borderRadius(8).backgroundColor(0x317aff).fontSize(40).width(70).height(50).margin(10).onClick(()=>{letnum1:number=parseInt(this.n1);letnum2:number=parseInt(this.n2);letnum3:number=num1/num2;this.n3=String(num3);})}
TextInput({text:$$this.n3}).id('n3').fontSize(30).fontWeight(FontWeight.Bold).margin(10).borderWidth(2).enabled(false)}.height('100%').width('100%')}}3.2系统内置UI组件介绍在深入介绍如何自定义用户UI界面之前,先对ArkUI中内置的常用基础组件的使用做简单介绍,以便更加直观地介绍UI界面设计和布局。3.2.1Text组件/Span组件/ImageSpan组件Text组件用于显示文本信息,显示在Text组件上的文本时不能被编辑的。例如,下面的例子使用Text组件显示“Hello,World”文字:Span也是文本组件,用于显示行内文本,但是,Span组件必须嵌入在Text组件中才能显示,单独的Span组件不会呈现任何内容。Text与Span同时配置文本内容时,Span内容覆盖Text内容。下面的例子通过在Text组件中嵌套多个Span组件显示多段文本:Text(‘Hello,World’).fontSize(30).border({width:1}).padding(10).width(300)在Text组件中除了可以嵌套Span组件外,还可以嵌套ImageSpan组件用于显示图片。例如,下面的例子在Text组件中嵌套ImageSpan组件用于显示图片:Text(){Span('我是Span1,').fontSize(16).fontColor(Color.Grey).decoration({type:TextDecorationType.LineThrough,color:Color.Red})Span('我是Span2').fontColor(Color.Blue).fontSize(16).fontStyle(FontStyle.Italic).decoration({type:TextDecorationType.Underline,color:Color.Black})Span(',我是Span3').fontSize(16).fontColor(Color.Grey).decoration({type:TextDecorationType.Overline,color:Color.Green})}.borderWidth(1).padding(10)Text(){//直接加载网络地址,需要填写一个具体的网络图片地址ImageSpan('/xxx.png').width(300).height(300)}ArkUI支持三个表示尺寸的单位,它们是:px、vp、fp。其中px就是像素单位,与HTML页面中的px含义完全相同;vp,VirtualPixel的缩写,也就是虚拟像素,这是鸿蒙特有的尺寸单位,通过vp,可以使同一个尺寸在不同分辨率的智能终端上具有相似的视觉效果。在所有尺寸属性的参数中,若没有指定尺寸单位,默认都是vp。fp与vp类似,只是fp是用于指定文字大小的尺寸单位。所有ArkUI组件都支持非常多的属性,包括通用属性和专有属性。通用属性是所有组件都支持的属性,典型的通用属性包括:尺寸设置、位置设置、布局约束、边框设置、背景设置、字体设置等。而专用属性则是各个不同组件所特有的。例如,对于Text组件,专有属性包括:textAlign用于设置文本段落在水平方向的对齐方式;textOverflow用于设置文本超长时的显示方式等。本书只对组件的常用属性做介绍,关于组件的详细属性及其使用,在使用ArkUI组件时,可以查阅鸿蒙SDK。3.2.2Button组件按钮组件,通常用于响应用户的点击操作,其外观类型包括胶囊按钮、圆形按钮、普通按钮、圆角矩形按钮。Button还可以作为容器使用,作为容器使用时可以通过添加子组件实现包含文字、图片等元素的按钮。例如,下面的例子显示一个普通按钮组件:Button('Ok',{type:ButtonType.Normal,stateEffect:true}).borderRadius(8).backgroundColor(0x317aff).width(90).height(40)下面的例子将Button作为容器使用,进而可以在Button组件上显示图片和文字:Button({type:ButtonType.Normal,stateEffect:true}){Row(){Image($r('app.media.loading')).width(20).height(40).margin({left:12})Text('loading').fontSize(12).fontColor(0xffffff).margin({left:5,right:12})}.alignItems(VerticalAlign.Center)}.borderRadius(8).backgroundColor(0x317aff).width(90).height(40)Button组件通常用于触发某些操作,可以绑定onClick事件来响应点击操作后的自定义行为。例如,下面的代码片段将对按钮的点击事件进行处理,其结果是在控制台显示一段ButtononClick文字信息:Button('Ok',{type:ButtonType.Normal,stateEffect:true}).onClick(()=>{('ButtononClick')})3.2.3Image组件使用Image组件显示图片,例如,在按钮中显示图标icon,在界面上显示图片以美化界面等。Image支持多种图片格式,包括png、jpg、bmp、svg、gif和heif等。Image显示的图片可以有多种来源,包括:本地图片、网络资源、resource资源、媒体库资源和base64等。下面针对这几种图片来源封面别进行介绍。1、显示本地图片在ets文件夹下创建子文件夹,例如,在ets目录下创建images子目录,然后将图片放置到images目录下。采用如下代码即可显示防止在images子目录下的a16.png图片:Image('images/a16.png').width(‘100%’).height(200)2、显示网络资源显示网络图片需申请权限ohos.permission.INTERNET,关于权限申请将在后续章节介绍。一旦申请了网络权限,Image组件的src参数为网络图片的链接。例如,下面的例子显示指定的网络图片:Image('/example.JPG')//实际使用时请替换为真实地址.width(200).height(200)3、resources资源使用资源格式可以显示图片,resources文件夹下的图片都可以通过$r资源id方式读取到并转换到Resource格式。例如,在工程Ch0301的资源目录下有名称为startIcon.png的图片,如图。此时,可以使用如下语句显示名称为startIcon.png的图片:Image($r('app.media.startIcon')).margin({top:10}).width(300).height(300)3.2.4InputText组件TextInput是输入框组件,允许用户输入文字信息,比如评论区的输入、聊天框的输入、表格的输入等,也可以结合其它组件构建功能页面,例如登录注册页面。例如,如下的语句将在界面上显示一个InputText输入框组件:TextInput()InputText组件提供了多种形式的输入框形态可供选择,包括:Normal基本输入模式、Password密码输入模式、Email邮箱地址输入模式、Number纯数字输入模式、PhoneNumber电话号码输入模式、USER_NAME用户名输入模式、NEW_PASSWORD新密码输入模式、NUMBER_PASSWORD纯数字密码输入模式、NUMBER_DECIMAL带小数点的数字输入模式、带URL的输入模式。这些输入形态可通过type属性进行设置。例如,下面的语句创建基本输入模式,也就是默认类型的输入框:TextInput().type(InputType.Normal)下面的语句创建小数数字输入框:TextInput().type(InputType.NUMBER_DECIMAL)还可以通过自定义样式设置InputText的外观、提示文字等。例如,下面的代码设置文字提示、默认文字及背景:TextInput({placeholder:'我是提示文本',text:'我是当前文本内容'}).backgroundColor(Color.Pink)文本框主要用于获取用户输入的信息,因此,可以对特定的事件进行响应和处理,例如,绑定onChange事件可以获取输入框内改变的内容,用户也可以使用通用事件来进行相应的交互操作。例如,下面的代码对InputText的事件进行处理:TextInput().onChange((value:string)=>{(value);}).onFocus(()=>{('获取焦点');})3.2.5Row组件/Column组件Row组件和Column组件都是线性布局组件,线性布局组件是常用也是最简单好用的布局组件。线性布局是其他布局的基础,其子元素在线性方向上(水平方向和垂直方向)依次排列。线性布局的排列方向由所选容器组件决定,Column容器内子元素按照垂直方向排列,Row容器内子元素按照水平方向排列。根据不同的排列方向,可选择使用Row或Column容器创建线性布局。通过Row组件和Column组件的相互嵌套,可以实现任意复杂的布局。例如,下面的例子在通过在Column组件中嵌套Row组件实现一个嵌套的布局界面:Column({space:20}){Text('space:20').fontSize(15).fontColor(Color.Gray).width('90%')Row().width('90%').height(50).backgroundColor(0xF5DEB3)Row().width('90%').height(50).backgroundColor(0xD2B48C)Row().width('90%').height(50).backgroundColor(0xF5DEB3)}.width('100%')还可以设置组件的对齐方式,如下面的代码所示:Column({}){Column(){}.width('80%').height(50).backgroundColor(0xF5DEB3)Column(){}.width('80%').height(50).backgroundColor(0xD2B48C)Column(){}.width('80%').height(50).backgroundColor(0xF5DEB3)}.width('100%').alignItems(HorizontalAlign.Start).backgroundColor('rgb(242,242,242)')3.3资源分类与访问在开发应用APP的过程中,经常需要用到颜色、字体、间距、图标等资源,这些资源在不同的设备或配置中的取值可能不同。为了提高资源管理的效率,同时也为了适应不同的设备类型,鸿蒙对程序用到的资源进行集中分类管理。3.3.1资源目录使用DevEco新建一个鸿蒙程序工程时,DevEco会为每个工程自动创建用于存放程序资源的目录。例如,对于Ch0301工程,其程序资源目录如图。在resources资源目录下有三个主要的子目录,分别是:1、base子目录,用于存放基本的资源,踏实最为基本的资源存放位置;2、dark子目录,当鸿蒙只能终端(例如手机)处于深色模式时,将首先在这个目录下寻找资源,若找不到,再从base子目录下寻找;3、rawfile子目录,用于存放例如音频、视频、大文件之类的资源,并采用独有的方式访问。仔细观察base子目录可以发现,在base子目录下还有三个二级子目录,它们是:1、element子目录,该子目录用于存放字符串资源、颜色资源、尺寸资源等;2、media子目录,该子目录用于存放图片相关资源;3、profile子目录,该子目录用于存储程序需要的配置文件。dark子目录与base子目录具有相同的二级子目录结构。在dark子目录可以根据需要创建相应的子目录:当鸿蒙只能终端处于深色模式时,首先从dark二级下寻找资源,若找不到,则再在从base的二级子目录下寻找。本质上,dark子目录下就是下文所描述的限定词子目录。除了base子目录和dark子目录外,还可以在resources目录下创建所谓的限定词子目录:针对特定的国家/语言/终端类型/横竖屏等创建的资源子目录。当终端处于限定词子所指定的状态时,则首先从满足条件的限定词子目录寻找资源,若找不到,则再在base子目录下寻找。3.3.2资源分类和资源访问程序中常用的资源包括:字符串资源、图片资源、颜色资源、尺寸资源等。鸿蒙要求把不同的资源防止在不同的资源二级子目录下,也就是,将资源分门别类的放置在base或者dark或者限定词子目录的element二级子目录以及media二级子目录下:字符串资源、颜色资源、尺寸资源放置到element子目录下的文件中,建议但不限于将字符串资源放置到string.json文件中,将颜色资源放置到color.json文件中,将尺寸资源放置到float.json文件中;图片资源以图片文件形式放置到media子目录下。一般情况下,将字符串资源保存到element二级子目录的的string.json文件中,string.json文件的格式如下例所示:{"string":[{"name":"string_hello","value":"Hello"},{"name":"string_world","value":"World"},{"name":"message_arrive","value":"Wewillarriveat%1$s."}]}一旦定义了字符串资源,便可以在程序中通过资源名字引用资源,引用资源的一般格式是:$r(‘资源全名’)。例如,下面的代码将字符串资源的值显示在Text组件中:Text($r('app.string.string_hello')).baselineOffset(0).fontSize(30).border({width:1}).padding(10).width(300)一般情况下将颜色资源保存到element二级子目录的的color.json文件中,color.json文件的格式如下例所示:{"color":[{"name":"color_hello","value":"#ffff0000"},{"name":"color_world","value":"#ff0000ff"}]}一旦定义了颜色资源,便可以在程序中通过资源名字引用该资源。例如,下面的代码使用颜色资源的值控制Text组件的颜色:Text($r('app.string.string_hello')).baselineOffset(0).fontSize(30).foregroundColor($r('app.color.color_hello')).border({width:1}).padding(10).width(300)将尺寸资源保存到element二级子目录的的float.json文件中,float.json文件的格式如下例所示:{"float":[{"name":"font_hello","value":"28.0fp"},{"name":"font_world","value":"20.0fp"}]}一旦定义了尺寸资源,便可以在程序中通过资源名字引用该资源。例如,下面的代码使用尺寸资源的值控制显示在Text组件中的文字大小:Text($r('app.string.module_desc')).baselineOffset(0).fontSize($r('app.float.font_hello')).foregroundColor($r('app.color.start_window_background')).border({width:1}).padding(10).width(300)程序要用到的图片资源,一般情况下直接放置在media二级子目录下即可,然后就可以通过诸如Image组件来引用图片资源。对于较大尺寸的图片资源也可以放置到rawfile资源目录。例如,将名称为a16.jpg的图片文件和a11.jpg的图片文件分别放置到media子目录和rawfile子目录下,然后,可以使用如下所示的Image组件显示它们:Image($r('app.media.a16')).margin({top:10}).width(300).height(300)
Image($rawfile('a11.jpg')).margin({top:10}).width(300).height(300)3.3.3访问系统资源鸿蒙系统提供了许多内置的资源,应用程序可以使用鸿蒙系统内置的系统资源,使用如下形式引用系统资源:$r('sys.type.resource_name')其中,sys表示系统资源;type为资源类型,取值包括“color”、“float”、“string”、“media”;resource_name为资源名称。例如,下面的代码引用了系统资源:Text('Hello').fontColor($r('sys.color.ohos_id_color_emphasize')).fontSize($r('sys.float.ohos_id_text_size_headline1')).fontFamily($r('sys.string.ohos_id_text_font_family_medium')).backgroundColor($r('sys.color.ohos_id_color_palette_aux1'))
Image($r('sys.media.ohos_app_icon')).border({color:$r('sys.color.ohos_id_color_palette_aux1'),radius:$r('sys.float.ohos_id_corner_radius_button'),width:2}).margin({top:$r('sys.float.ohos_id_elements_margin_horizontal_m'),bottom:$r('sys.float.ohos_id_elements_margin_horizontal_l')}).height(200).width(300)3.4细说UI从上面的算术运算的例子可以看出,ArkUI提供了一系列关键字及注解用以创建用户UI界面,本节对创建UI界面进行详细介绍。3.4.1使用@Component和@Entry以及struct构建界面ArkUI提供一系列基础组件的同时,也提供了自定义组件的机制。在定义用户UI界面时,可以使用ArkUI提供的基础组件,还可以将一些常用的界面组件自定义为组件,然后在程序中复用这些组件,进而提高变成效率。下面的例子中,程序首先自定义了一个名称为COne的组件,然后在入口组件,也就是使用了@Entry标注的组件,调用这个自定义组件进而构建程序的UI界面。为了新建一个界面,在程序工程Ch0301的子目录entry下,右击pages子目录,并选择“ArkTSFile”,如图所示,然后在弹出的对话框中输入Other.ets文件名,DevEco将创建名称为Other.ets的文件。然后修改Other.ets文件为如下代码:@ComponentstructCOne{w1:string='';w2:string='';
build(){Column(){Button(this.w1,{type:ButtonType.Capsule,stateEffect:true}).width('95%').borderRadius(8).backgroundColor(0x317aff).fontSize(40).margin(20)Button(this.w2,{type:ButtonType.Capsule,stateEffect:true}).width('95%').borderRadius(8).backgroundColor(0x317aff).fontSize(40).margin({bottom:20})}}}
@Entry@ComponentstructOther{build(){Column(){Row(){COne({w1:'Hello',w2:'World'}).width('50%')Image($rawfile('a11.jpg')).width('45%').borderRadius(20).margin({left:10})}COne({w1:'按钮1',w2:'按钮2'}).width('100%')}}}3.4.2显示程序UI界面观察“ets/pages”页面目录,可以发现在这个目录下有两个页面:名字为Index.ets的界面文件和名字为Other.ets的界面文件。为了查看Other.ets这个界面的效果,首先打开文件“resources/base/profile/main_pages.json“,修改文件为如下内容:之所以要在这个文件中添加界面"pages/Other",是因为鸿蒙规定所有的界面都需要在这个文件中注册。{"src":["pages/Index","pages/Other"]}再修改“ets/entryability/EntryAbility.ets“文件的onWindowStageCreate()函数:onWindowStageCreate(windowStage:window.WindowStage):void{//Mainwindowiscreated,setmainpageforthisability(DOMAIN,'testTag','%{public}s','AbilityonWindowStageCreate');
windowStage.loadContent('pages/Other',(err)=>{if(err.code){hilog.error(DOMAIN,'testTag','Failedtoloadthecontent.Cause:%{public}s',JSON.stringify(err));return;}(DOMAIN,'testTag','Succeededinloadingthecontent.');});}3.4.3自定义组件的生命周期在鸿蒙系统中,组件的状态是可以被感知的,也就是,组件是有生命周期的:组件在不同的不同阶段会被系统回调指定的方法。组件具有如下几个生命周期方法:1、aboutToAppear:组件即将出现时该方法会被系统回调,具体时机为在创建自定义组件的新实例后,在执行其build()函数之前执行。2、onDidBuild:组件build()函数执行完成之后回调该方法,开发者可以在这个阶段进行埋点数据上报等不影响实际UI的功能。3、aboutToDisappear:aboutToDisappear函数在自定义组件被销毁之前被回调。为了直观观察到组件的生命周期方法被回调,在Other.ets中为COne组件添加生命周期方法。修改后的Other.ets为如下内容:import{hilog}from'@kit.PerformanceAnalysisKit';
constDOMAIN=0x2000;
@ComponentstructCOne{w1:string='';w2:string='';
//组件生命周期aboutToAppear(){(DOMAIN,'LIFECYCLE','COneaboutToAppear');}
//组件生命周期onDidBuild(){(DOMAIN,'LIFECYCLE','COneonDidBuild');}
//组件生命周期aboutToDisappear(){(DOMAIN,'LIFECYCLE','COneaboutToDisappear');}
build(){Column(){Button(this.w1,{type:ButtonType.Capsule,stateEffect:true}).width('95%').borderRadius(8).backgroundColor(0x317aff).fontSize(40).margin(20)Button(this.w2,{type:ButtonType.Capsule,stateEffect:true}).width('95%').borderRadius(8).backgroundColor(0x317aff).fontSize(40).margin({bottom:20})}}}
@Entry@ComponentstructOther{build(){Column(){Row(){COne({w1:'Hello',w2:'World'}).width('50%')Image($rawfile('a11.jpg')).width('45%').borderRadius(20).margin({left:10})}COne({w1:'按钮1',w2:'按钮2'}).width('100%')}}}3.4.4程序UI界面的生命周期观察Other组件:它被@Component注解,同时又被@Entry注解,因此,Other组件是一个自定义组件的同时,也是一个入口UI。因为Other组件是一个自定义组件,因此,它具有普通自定义组件一样的组件生命周期;又因为它是一个入口UI,因此,它还具有入口UI的生命周期,也就是,它还具有作为UI页面所特有的生命周期。UI页面包括如下几个生命周期方法,它们的含义及其被调用时机如下:1、 onPageShow:页面每次显示时触发一次;2、 onPageHide:页面每次隐藏时触发一次;3、 onBackPress:当用户点击返回按钮时触发。为了观察页面的声明周期,修改Other.ets为如下代码:import{hilog}from'@kit.PerformanceAnalysisKit';
constDOMAIN=0x2000;
@ComponentstructCOne{w1:string='';w2:string='';
//组件生命周期aboutToAppear(){(DOMAIN,'LIFECYCLE','COneaboutToAppear');}
//组件生命周期onDidBuild(){(DOMAIN,'LIFECYCLE','COneonDidBuild');}
//组件生命周期aboutToDisappear(){(DOMAIN,'LIFECYCLE','COneaboutToDisappear');}
build(){Column(){Button(this.w1,{type:ButtonType.Capsule,stateEffect:true}).width('95%').borderRadius(8).backgroundColor(0x317aff).fontSize(40).margin(20)Button(this.w2,{type:ButtonType.Capsule,stateEffect:true}).width('95%').borderRadius(8).backgroundColor(0x317aff).fontSize(40).margin({bottom:20})}}}
@Entry@ComponentstructOther{//只有被@Entry装饰的组件才可以调用页面的生命周期onPageShow(){(DOMAIN,'LIFECYCLE','onPageShow');}
//只有被@Entry装饰的组件才可以调用页面的生命周期onPageHide(){(DOMAIN,'LIFECYCLE','onPageHide');}
//只有被@Entry装饰的组件才可以调用页面的生命周期onBackPress(){(DOMAIN,'LIFECYCLE','onBackPress');//返回true表示页面自己处理返回逻辑,不进行页面路由;//返回false表示使用默认的路由返回逻辑,不设置返回值按照false处理returnfalse;}
build(){Column(){Row(){COne({w1:'Hello',w2:'World'}).width('50%')Image($rawfile('a11.jpg')).width('45%').borderRadius(20).margin({left:10})}COne({w1:'按钮1',w2:'按钮2'}).width('100%')}}}3.5UI组件装饰器及其使用为了提高自定义组件的灵活性和编码效率,ArkUI提供了一系列装饰器用于代码复用、样式复用等功能。本节对最常用的组件装饰器进行介绍。3.5.1@Builder:自定义构建函数@Builder装饰器提供了一种轻量的UI元素复用机制,开发者可以将重复使用的UI元素抽象成一个方法并使用@Builder装饰器装饰,然后在build方法里调用。使用@Builder修饰的方法称为自定义构造器方法。@Builder装饰器有两种使用方式:装饰定义在自定义组件内部的私有构建函数和装饰定义在组件外部的全局构建函数。通过一个例子了解@Builder的使用。这个例子定义两个使用@Builder装饰器装饰的方法,一个为全局方法,另一个是局部方法。在组件的build()方法中调用这两个方法构建指定的组件元素。首先在“/ets/pages”目录下新建名称为TBuilder.ets文件,然后修改内容为如下代码:classGParam{str_value:string='Hello';num_value:number=0;}
@BuilderfunctiongBuilder(param:GParam){Column(){Text(`str_value:${param.str_value}`)Text(`num:${param.num_value}`)}}
@Entry@ComponentstructParent{@StateobjParam:GParam=newGParam();//@State装饰器将在下一节介绍
@BuildershowImage(path:string){Image($rawfile(path)).width('95%').borderRadius(20)}
build(){Column(){Text('通过调用@Builder渲染UI界面').margin({top:50}).fontSize(20)gBuilder({str_value:this.objParam.str_value,num_value:this.objParam.num_value})Line().width('100%').height(10).backgroundColor('#000000').margin(10)this.showImage('a11.jpg')Button('点击改变参数值').margin(50).onClick(()=>{this.objParam.str_value='HelloWorld';this.objParam.num_value=1;})}}}为了查看这个UI页面效果,修改“/resources/base/profile”目录下的main_pages.json文件为如下内容:再修改“ets/entryability/EntryAbility.ets“文件的onWindowStageCreate()函数中的语句:
windowStage.loadContent('pages/Other',(err)=>{为:windowStage.loadContent('pages/TBuilder',(err)=>{{"src":["pages/Index","pages/Other","pages/TBuilder"]}3.5.2@BuilderParam:引用@Builder函数简单来说,@BuilderParam用来装饰指向@Builder方法的变量,进而可以通过被装饰的变量引用@Builder装饰器所装饰的函数。看一个例子。@ComponentstructChildBuilderParam{@BuildercustomBuilder(){};@BuilderParamcustomBuilderParam:()=>void=this.customBuilder;
build(){Column(){this.customBuilderParam()}}}
@Entry@ComponentstructExBuilderParam{@BuildercomponentBuilder01(){Text(`Text:Parentbuilder`)}
@BuildercomponentBuilder02(){Button(`Button:Parentbuilder`)}
build(){Column(){ChildBuilderParam({customBuilderParam:ponentBuilder01})ChildBuilderParam({customBuilderParam:ponentBuilder02})}}}在@Entry组件ExBuilderParam的build()函数中,调用了两次ChildBuilderParam组件,并分别传递两个不同的@Builder构造函数:
ChildBuilderParam({customBuilderParam:ponentBuilder01})ChildBuilderParam({customBuilderParam:ponentBuilder02})因此,在程序的主界面中将分别显示一个Text组件和一个Button组件。3.5.3@LocalBuilder:维持组件父子关系@LocalBuilder装饰器与@Builder装饰器的作用类似,都用于装饰方法,使得被装饰方法可以在组件的build()方法中被调用。它们之间的主要区别在于对this指针的引用:@LocalBuilder拥有和局部@Builder相同的功能,且比局部@Builder能够更好的确定组件的父子关系和状态管理的父子关系。下面通过一个例子来说明@LocalBuilder装饰器与@Builder装饰器的区别。@ComponentstructChild{label:string='Child';@BuilderParamcustomBuilderParam:()=>void;
build(){Column(){this.customBuilderParam()}}}
@Entry@ComponentstructExampleLocalBuilder{label:string='Parent';
//@LocalBuilder@BuildercomponentBuilder(){Button(`${this.label}`).width('100%').margin({top:50})}
build(){Column(){Child({customBuilderParam:ponentBuilder})}}}@Entry@ComponentstructExampleLocalBuilder{label:string='Parent';
@LocalBuilder//@BuildercomponentBuilder(){Button(`${this.label}`).width('100%').margin({top:50})}
build(){Column(){Child({customBuilderParam:ponentBuilder})}}}3.5.4@Styles:定义组件重用样式简单来说,@Styles装饰用于定义组件重用样式。如果每个组件的样式都需要单独设置,在开发过程中会出现大量代码在进行重复样式设置,@Styles装饰器可以将多条样式设置提炼成一个方法,直接在组件声明的位置调用。通过@Styles装饰器可以快速定义并复用自定义样式。看一个例子。//定义为全局的@Styles封装样式,必须有function关键字@StylesfunctionglobalFancy(){.width(150).height(100).backgroundColor(Color.Pink)}
@Entry@ComponentstructFancyUse{@StateheightValue:number=100;//定义在组件内的@Styles封装的样式@Stylesfancy(){.width(200).height(this.heightValue).backgroundColor(Color.Yellow).onClick(()=>{this.heightValue=200})}
build(){Column({space:10}){//使用全局的@Styles封装的样式Text('FancyA').globalFancy().fontSize(30)//使用组件内的@Styles封装的样式Text('FancyB').fancy().fontSize(30)}}}3.5.5@Extend:定义扩展组件样式除了可以使用@Styles用于样式的重用外,还可以使用@Extend装饰器扩展组件样式。@Extend装饰器的一般使用格式为:@Extend(UIComponentName)functionfunctionName{...}其中的UIComponentName是任何已有的组件名。看一个例子。@Extend(Text)functionfancyText(weightValue:number,color:Color){.fontStyle(FontStyle.Italic).fontWeight(weightValue).backgroundColor(color)}
@Entry@ComponentstructFancyUse{@Statelabel:string='HelloWorld'
build(){Row({space:10}){Text(`${this.label}`).fancyText(100,Color.Blue)Text(`${this.label}`).fancyText(200,Color.Pink)Text(`${this.label}`).fancyText(300,Color.Orange)}.margin('20%')}}3.6渲染控制在使用ArkUI开发界面的过程中,可以使用渲染控制语句来辅助UI的构建。这些渲染控制语句包括:控制组件是否显示的条件渲染语句,基于数组数据快速生成组件的循环渲染语句,针对大数据量场景的数据懒加载语句,针对混合模式开发的组件渲染语句。本节对最为常用的条件渲染和循环渲染进行介绍。3.6.1if/else条件渲染条件渲染可根据应用的不同状态,使用if、else和elseif渲染对应状态下的UI内容。@Entry@ComponentstructMyIfComponent{@Statecount:number=0;
build(){Column(){Text(`count=${this.count}`)
if(this.count>0){Text(`countispositive`).fontColor(Color.Green)}elseif(this.count==0){Text(`countiszero`).fontColor(Color.Blue)}else{Text(`countisnegative`).fontColor(Color.Red)}
Button('increasecount').onClick(()=>{this.count++;})
Button('decreasecount').onClick(()=>{this.count--;})}}}3.6.2ForEach循环渲染ForEach基于集合/数组类型数据进行循环渲染,需要与容器组件配合使用,且ForEach返回的组件应当是允许包含在ForEach父容器组件中的子组件。在ForEach循环渲染过程中,系统会为每个数组元素生成一个唯一且持久的键值,用于标识对应的组件。当这个键值变化时,ArkUI框架将视为该数组元素已被替换或修改,并会基于新的键值创建一个新的组件。看一个例子。@Entry@ComponentstructTForEachParent{simpleList:Array<string>=['one','two','three'];
build(){Row(){Column(){ForEach(this.simpleList,(item:string,index:number)=>{TForEachChildItem({item:index+':'+item})},(item:string,index:number)=>item)}.width('100%').height('100%')}.height('100%').backgroundColor(0xF1F3F5)}}
@ComponentstructTForEachChildItem{@Propitem:string;
build(){Text(this.item).fontSize(50)}}3.7案例:图来图往本节通过编写一个综合性的例子对本章以及本章之前的知识内容进行总结
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025-2026学年河南省周口市项城市两校八年级下学期期末地理试卷(含答案)
- 河北单招考试试题及答案分析题
- 2026年保安员职业技能考试笔试试题含答案
- 2026年“全国安全生产月”《安全知识》竞赛题库及答案
- 2026年西城事业单位考试试题及答案
- 区块链电子信息产业链
- 2026年考前复习口腔组织病理学模拟试题附答案
- 2026年安全生产管理知识竞赛笔试考试考题含答案
- 2026年药品质量管理制度培训题库及答案
- 2026年人力技能试题及答案
- 海南文昌恒晟环保炭化加工有限公司椰壳碳化、水烟碳加工项目(重大变动)环境影响报告表
- C20混凝土垫层施工方案
- 冠心病超声心动图诊断与应用
- 操作系统-002-国开机考复习资料
- 2025国家开放大学《人类发展与环境保护》形成性考核123答案+终结性考试答
- 酒店拆除改造工程专项拆除施工方案
- 住建部房屋市政工程安全生产标准化指导图册
- 先天性胆道闭锁(共29张课件)
- 人教版(2024新版)八年级上册物理《开启科学探索之旅》教学设计
- 人教版三年级《语文下册》期末试卷(下载)
- 马工程《公共财政概论》课后习题库(含)参考答案(可做期末复习和试卷)
评论
0/150
提交评论