版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
长沙民政职业技术学院鸿蒙应用开发
本任务需要实现一个联系人的应用。1.主界面能显示目前用户保存的所有联系人信息(性别图标、姓名、电话)2.在通讯录主界面点击新增图标时,进入新增联系人界面。如果用户按界面要求填入电话、联系人名称、性别等信息,点击保存图标,则将在系统中保存联系人信息,并自动追加到主界面已有联系人的最后;如果用户点击了对话框的取消图标,则不会保存新建联系人对话框输入的信息且自动回到主界面。项目三创建通讯录主界面新建联系人界面联系人详情界面主界面学习目标知识目标能力目标素养目标教学目标掌握常用UI组件TextInput、Search的常见方法。掌握线性界面布局。掌握关系型数据库的使用方法。掌握使用列表List及ListItem显示条目数据的方法。掌握页面路由以及参数传递方法。熟练掌握鸿蒙移动应用开发的基本流程。能熟练应用线性布局编写界面。能熟练利用List及ListItem显示列表。能熟练使用关系数据库进行插入、修改、删除、查询数据。能熟练掌握页面路由及参数传递。培养并践行编码规范意识,变量命名可读、格式规范,注释清晰易读。培养自主学习能力,通过阅读文档,学习新知并能在实际项目中运用、解决问题。任务一实现主界面和新增联系人界面任务二向通讯录增加联系人任务三显示通讯录联系人列表任务四查看联系人详情目录CONTENTS实现主界面和新增联系人界面任务描述
通讯录的主界面需求如下面左图所示,请实现主界面。当用户点击了新增图标时,界面跳转到新增界面,新增界面如右图所示。在新增界面,点击标题栏的回退图标,将回到主界面。主界面联系人详情界面任务重点及难点任务目的1.知识目标:(1)掌握常用UI组件Search、TextInput的常见方法;(2)掌握使用router进行页面跳转的方法;2.能力目标:(1)熟练掌握鸿蒙移动开发的基本流程中的创建项目、创建界面布局的过程;(2)能熟练应用线性布局和层叠布局编写界面;(3)能熟练使用router实现页面跳转3.素质目标:(1)通过界面布局培养从整体到局部的思维;(2)学习读API文档;重难点重点:(1)能熟练使用router实现页面跳转(2)能熟练应用线性布局和层叠布局编写界面;难点:(1)能熟练应用线性布局和层叠布局编写界面;1.1完成任务所需知识清单1Search2TextInput3router1.1完成任务所需知识清单-Search组件当需要对所浏览内容根据关键字搜索特定条目时就可以用到搜索框组件。接口定义如下:Search(options?:{value?:string;placeholder?:string;icon?:string;controller?:SearchController})1、Search组件--实现搜索框的组件接口参数说明表参数名参数类型必填参数描述valuestring否设置当前显示的搜索文本内容placeholderstring否设置无输入时的提示文本iconstring否设置搜索图标路径,默认使用系统搜索图标,图标支持的图源格式:svg、jpg和pngcontrollerSearchController否设置Search组件控制器1.1完成任务所需知识清单-Search组件除支持UI组件的通用属性(比如Width,Height等),还支持其余属性1、Search组件实现搜索框的组件名称参数类型描述searchButtonstring搜索框末尾搜索按钮文本内容,默认无搜索按钮placeholderColorResourceColor设置placeholder文本颜色placeholderFontFont设置placeholder文本样式textFontFont设置搜索框内输入文本样式textAlignTextAlign设置文本在搜索框中的对齐方式。默认值:TextAlign.StartcopyOption9+CopyOptions设置输入的文本是否可复制1.1完成任务所需知识清单-Search组件除支持通用事件外,还支持其余事件1.Search组件实现搜索框的组件名称功能描述onSubmit(callback:(value:string)=>void)点击搜索图标、搜索按钮或者按下软键盘搜索按钮时触发该回调。-value:当前搜索框中输入的文本内容onChange(callback:(value:string)=>void)输入内容发生变化时,触发该回调。-value:当前搜索框中输入的文本内容1.1完成任务所需知识清单-Search组件1、Search组件实现搜索框的组件示例:实现一个如图的搜索框。1.1完成任务所需知识清单-Search组件1
@Entry2
@Component3
structSearchExample{4
@StatechangeValue:string=''5
@StatesubmitValue:string=''6
controller:SearchController=newSearchController()78
build(){9
Column(){10
Text('onSubmit:'+this.submitValue).fontSize(18).margin(15)11
Text('onChange:'+this.changeValue).fontSize(18).margin(15)12
Search({value:this.changeValue,placeholder:'Typetosearch...',controller:this.controller})13
.searchButton('SEARCH')14
.width(400)15
.height(40)1.1完成任务所需知识清单-Search组件16
.placeholderColor(Color.Grey)17
.placeholderFont({size:14,weight:400})18
.textFont({size:14,weight:400})19
.onSubmit((value:string)=>{20
this.submitValue=value21
})22
.onChange((value:string)=>{23
this.changeValue=value24
})25
.margin(20)26
Button('SetcaretPosition1')27
.onClick(()=>{28
//设置光标位置到输入的第一个字符后29
this.controller.caretPosition(1)30
})31
}.width('100%')32
}33
}1.1完成任务所需知识清单-TextInput组件接口参数说明表TextInput是单行文本输入框组件,可以设置输入文本的数据类型为字符或者数字或者密码,可以设置输入框的默认输入内容等属性。接口定义如下:TextInput(value?:{placeholder?:ResourceStr,text?:ResourceStr,controller?:TextInputController})参数名参数类型必填参数描述placeholderResourceStr否设置无输入时的提示文本textResourceStr否设置输入框当前的文本内容controller8+TextInputController否设置TextInput控制器1.1完成任务所需知识清单-TextInput组件
TextInput组件文本输入框除支持通用属性外,还支持其余属性名称参数类型描述typeInputType设置输入框类型。默认值:InputType.Normal;枚举值可以选择Normal,Password,Email,Number,PhoneNumberplaceholderColorResourceColor设置placeholder文本颜色placeholderFontFont设置placeholder文本样式enterKeyTypeEnterKeyType设置输入法回车键类型,目前仅支持默认类型显示。默认值:EnterKeyType.DonemaxLengthnumber设置文本的最大输入字符数copyOptionCopyOptions设置输入的文本是否可复制。设置CopyOptions.None时,当前TextArea中的文字无法被复制或剪切,仅支持粘贴showPasswordIconboolean密码输入模式时,输入框末尾的图标是否显示。默认值:truestyleTextInputStyle设置输入框为默认风格或内联输入风格。默认值:TextInputStyle.DefaulttextAlignTextAlign设置输入文本在输入框中的对齐方式。默认值:TextAlign.Start
事件接口名称功能描述onChange(callback:(value:string)=>void)输入内容发生变化时,触发该回调。value:输入的文本内容。onSubmit(callback:(enterKey:EnterKeyType)=>void)按下输入法回车键触发该回调,返回值为当前输入法回车键的类型。enterKeyType:输入法回车键类型。具体类型见EnterKeyType枚举说明。onEditChanged(callback:(isEditing:boolean)=>void)(deprecated)输入状态变化时,触发该回调。从API8开始,建议使用onEditChange。onEditChange(callback:(isEditing:boolean)=>void)8+输入状态变化时,触发该回调。isEditing为true表示正在输入。1.1完成任务所需知识清单-TextInput组件
TextInput样例1.1完成任务所需知识清单-TextInput组件1@Entry2@Component3structTextInputExample{4@Statetext:string=''5controller:TextInputController=newTextInputController()67build(){8Column(){9TextInput({placeholder:'inputyourword...',controller:this.controller})10.placeholderColor(Color.Grey)11.placeholderFont({size:14,weight:400})12.caretColor(Color.Blue)13.width(400)14.height(40)15.margin(20)16.fontSize(14)17.fontColor(Color.Black)18.onChange((value:string)=>{19this.text=value20})
TextInput样例1.1完成任务所需知识清单-TextInput组件21Text(this.text)22Button('SetcaretPosition1')23.margin(15)24.onClick(()=>{25//将光标移动至第一个字符后26this.controller.caretPosition(1)27})28//密码输入框29TextInput({placeholder:'inputyourpassword...'})30.width(400)31.height(40)32.margin(20)33.type(InputType.Password)34.maxLength(9)35.showPasswordIcon(true)36//内联风格输入框37TextInput({placeholder:'inlinestyle'})38.width(400)39.height(50)40.margin(20)41.borderRadius(0)42.style(TextInputStyle.Inline)43}.width('100%')44}
页面路由指在应用程序中实现不同页面之间的跳转和数据传递。HarmonyOS提供了Router模块,通过不同的url地址,可以方便地进行页面路由,访问不同的页面。两种跳转模式,决定了目标页是否会替换当前页:●
router.pushUrl():目标页不会替换当前页,而是压入页面栈。这样可以保留当前页的状态,并且可以通过返回键或者调用router.back()方法返回到当前页。●
router.replaceUrl():目标页会替换当前页,并销毁当前页。这样可以释放当前页的资源,并且无法返回到当前页。1.1完成任务所需知识清单-router页面路由
两种实例模式,分别是Standard和Single。这两种模式决定了目标url是否会对应多个实例。●
Standard:标准实例模式,也是默认情况下的实例模式。每次调用该方法都会新建一个目标页,并压入栈顶。●
Single:单实例模式。即如果目标页的url在页面栈中已经存在同url页面,则离栈顶最近的同url页面会被移动到栈顶,并重新加载;如果目标页的url在页面栈中不存在同url页面,则按照标准模式跳转。1.1完成任务所需知识清单-router页面路由
场景一:有一个主页(Home)和一个详情页(Detail),希望从主页点击一个商品,跳转到详情页。同时,需要保留主页在页面栈中,以便返回时恢复状态。这种场景下,可以使用pushUrl()方法,并且使用Standard实例模式(标准实例模式下,router.RouterMode.Standard参数可以省略)。1//在Home页面中2functiononJumpClick():void{3router.pushUrl({4url:'pages/Detail'//目标url5},router.RouterMode.Standard,(err)=>{6if(err){7console.error(`InvokepushUrlfailed,codeis${err.code},messageis${err.message}`);8return;9}10('InvokepushUrlsucceeded.');11});12}1.1完成任务所需知识清单-router页面路由
场景二:有一个登录页(Login)和一个个人中心页(Profile),希望从登录页成功登录后,跳转到个人中心页。同时,销毁登录页,在返回时直接退出应用。这种场景下,可以使用replaceUrl()方法,并且使用Standard实例模式(或者省略)。场景三:有一个设置页(Setting)和一个主题切换页(Theme),希望从设置页点击主题选项,跳转到主题切换页。同时,需要保证每次只有一个主题切换页存在于页面栈中,在返回时直接回到设置页。这种场景下,可以使用pushUrl()方法,并且使用Single实例模式。1.1完成任务所需知识清单-router页面路由
场景四:有一个搜索结果列表页(SearchResult)和一个搜索结果详情页(SearchDetail),希望从搜索结果列表页点击某一项结果,跳转到搜索结果详情页。同时,如果该结果已经被查看过,则不需要再新建一个详情页,而是直接跳转到已经存在的详情页。这种场景下,可以使用replaceUrl()方法,并且使用Single实例模式。1.3完成任务所需知识清单-router页面路由
当用户在一个页面完成操作后,通常需要返回到上一个页面或者指定页面,这就需要用到页面返回功能。方式一:返回到上一个页面。1router.back();方式二:返回到指定页面。1router.back({2url:'pages/Home'3});1.3完成任务所需知识清单-router页面路由输入主题完成应用的主界面UI框架设计1.2任务1的实施任务目标创建主界面
(1)创建项目启动开发工具DevEcoStudio,创建一个新项目,选择“EmptyAbility”。在项目配置对话框中设置项目名为MyContacts,项目类型为Application,其他相关设置参见下图中的设置。完成这些选项设置后按“Finish”按钮创建项目。1.2任务1的实施
(2)主界面UI设计实现主界面页面效果,页面的最外层用Stack布局,里面包裹一个Column(其中一行包含一个文本,另一行包含一个搜索框)和一个新增按钮。新增按钮位置用绝对定位;联系人文本处于本行的正中间,可以用到行的justifyContent(FlexAlign.Center)属性。1.2任务1的实施
(3)新建联系人界面UI设计新建联系人界面由5行垂直排列组成,在最外层用一个Column,包裹5行Row,每行Row内部呈横排线性排列。标题栏要求取消和保存图标在两边,标题“新建联系人”居中。1.2任务1的实施
(4)页面路由设置当用户点击新增按钮后,跳转到新增页面;在新增页面点击左上角的取消图标后跳回到主界面;1.2任务1的实施完成了项目主要的界面设计和新建联系人界面及两个页面之间的相互跳转完成的编码Search组件TextInput组件router页面跳转学到的知识任务小结任务小结任务2向通讯录增加联系人02任务目标及重点难点任务描述在本任务中,要求当用户用户输入联系人信息以后,将联系人信息保存到数据库,并在后台打印输出数据库中所有用户信息。如果用户选择不保存,即取消,则新录入的联系人信息不会保存到数据库。任务目的1、知识目标:掌握关系型数据库的使用方法;2、能力目标:能熟练使用关系数据库进行插入、修改、删除、查询数据;3、素质目标:(1)培养良好的编程习惯重难点1、重点:关系数据库操作2、难点:关系数据库操作0201关系型数据库数据库接口2.1完成任务所需知识清单
关系型数据库对应用提供通用的操作接口,底层使用SQLite作为持久化存储引擎,支持SQLite具有的数据库特性,包括但不限于事务、索引、视图、触发器、外键、参数化查询和预编译SQL语句。2.1完成任务所需知识清单——关系型数据库
接口名称描述getRdbStore(context:Context,config:StoreConfig,callback:AsyncCallback<RdbStore>):void获得一个相关的RdbStore,操作关系型数据库,用户可以根据自己的需求配置RdbStore的参数,然后通过RdbStore调用相关接口可以执行相关的数据操作。executeSql(sql:string,bindArgs:Array<ValueType>,callback:AsyncCallback<void>):void执行包含指定参数但不返回值的SQL语句。insert(table:string,values:ValuesBucket,callback:AsyncCallback<number>):void向目标表中插入一行数据。update(values:ValuesBucket,predicates:RdbPredicates,callback:AsyncCallback<number>):void根据RdbPredicates的指定实例对象更新数据库中的数据。delete(predicates:RdbPredicates,callback:AsyncCallback<number>):void根据RdbPredicates的指定实例对象从数据库中删除数据。query(predicates:RdbPredicates,columns:Array<string>,callback:AsyncCallback<ResultSet>):void根据指定条件查询数据库中的数据。deleteRdbStore(context:Context,name:string,callback:AsyncCallback<void>):void删除数据库。2.1完成任务所需知识清单——数据库接口数据库使用示例
letcontext=featureAbility.getContext();constSTORE_CONFIG={name:'RdbTest.db',//数据库文件名//@ts-ignoresecurityLevel:relationalStore.SecurityLevel.S1//数据库安全级别};exportdefaultclassApplicationdbAbilityextendsUIAbility{onCreate(want,launchParam){(0x0000,'testTag','%{public}s','AbilityonCreate');}
onWindowStageCreate(windowStage:window.WindowStage){2.1完成任务所需知识清单——数据库接口数据库使用示例
2.1完成任务所需知识清单——数据库接口relationalStore.getRdbStore(this.context,STORE_CONFIG,(err,store)=>{if(err){console.error(`FailedtogetRdbStore.Code:${err.code},message:${err.message}`);return;}(`SucceededingettingRdbStore.`);store.executeSql(SQL_CREATE_TABLE);//创建数据表//这里执行数据库的增、删、改、查等操作constvalueBucket={'NAME':'Lisa','AGE':18,'SALARY':100.5,'CODES':newUint8Array([1,2,3,4,5])};数据库使用示例
2.1完成任务所需知识清单——数据库接口letpredicates=newrelationalStore.RdbPredicates("EMPLOYEE");//@ts-ignorepredicates.equalTo('NAME','Rose');store.query(predicates,['ID','NAME','AGE','SALARY','CODES'],(err,resultSet)=>{if(err){console.error(`Failedtoquerydata.Code:${err.code},message:${err.message}`);return;}(`ResultSetcolumnnames:${resultSet.columnNames}`);(`ResultSetcolumncount:${resultSet.columnCount}`);})
数据库使用示例
2.1完成任务所需知识清单——数据库接口store.insert('EMPLOYEE',valueBucket,(err,rowId)=>{if(err){console.error(`Failedtoinsertdata.Code:${err.code},message:${err.message}`);return;}(`Succeededininsertingdata.rowId:${rowId}`);})});}}}第一步:搭建联系人模型第二步:初始化数据库,创建联系人表第三步:编写数据库的新增、查询接口第四步:在新增界面为确认图标添加单击事件响应任务1实现了主界面和新建联系人见面;该任务需完成:在新增联系人界面,当用户点击确认图标时,保存用户输入的联系人信息。任务目标实施步骤2.2任务2的实施
(1)搭建联系人模型在src->main->ets->common下新建文件夹bean,创建ets文件ContactData.ets,文件结构如图所示1exportdefaultclassContactData{2id:number;3accountType:number;4name:string;5phoneNumber:string;6beizhu:string;78constructor(id:number,accountType:number,name:string,phoneNumber:string,beizhu:string){9this.id=id;10this.accountType=accountType;11=name;12this.phoneNumber=phoneNumber;13this.beizhu=beizhu;14}16}2.2任务2的实施
1.初始化数据库,创建联系人表1exportdefaultclassCommonConstants{2staticreadonlySEARCH_TEXT='搜索';3staticreadonlyFULL_WIDTH='100%';4staticreadonlyFULL_HEIGHT='100%';5staticreadonlyFULL_SIZE=1;6staticreadonlyPOSITION_X='80%';7staticreadonlyPOSITION_Y='85%';89staticreadonlySTORE_CONFIG={10name:'database.db',11//@ts-ignore12securityLevel:relationalStore.SecurityLevel.S113};14/**15*Accounttableconfig.16*/17staticreadonlyCONTACT_TABLE={18tableName:'accountTable',sqlCreate:'CREATETABLEIFNOTEXISTSaccountTable(idINTEGERPRIMARYKEYAUTOINCREMENT,accountTypeINTEGER,'+'nameTEXT,phoneNumber1TEXT,beizhuTEXT)',columns:['id','accountType','name','phoneNumber1','beizhu']20};19}20exportconstImageList={21222.2任务2的实施
(2)创建Rdb.ets文件,实现数据库创建、查询、插入等最基本的操作2.2任务2的实施
2.创建Rdb.ets文件,实现数据库创建、查询、插入等最基本的操作2.2任务2的实施
(2)创建Rdb.ets文件,实现数据库创建、查询、插入等最基本的操作2.2任务2的实施
(3)创建ContactTable.ets文件,基于Rdb中提供的方法实现业务数据的增、删、改、查操作。2.2任务2的实施
(3)创建ContactTable.ets文件,基于Rdb中提供的方法实现业务数据的查询操作。2.2任务2的实施
(3)创建ContactTable.ets文件,基于Rdb中提供的方法实现业务数据的增、删、改、查操作。2.2任务2的实施
(3)创建ContactTable.ets文件,基于Rdb中提供的方法实现业务数据的查询操作。2.2任务2的实施
(4)在新增界面为确认图标添加单击事件响应当用户在新增界面中输入姓名、电话等信息时,需要将用户输入的值保存到一个ContactData类型的变量(此处命名为newAccount)对应字段中,在用户点击确认按钮时,将这个newAccount插入到数据库中。1
TextInput({placeholder:'姓名'})2.width(380)3.height(40)4.margin($r('app.float.edge_size_MM'))5.fontSize($r('app.float.font_size_M'))6.fontColor(Color.Black)7.onChange((value:string)=>{8this.newA=value9})获取输入文本值的方法如表所示,为TextInput增加onChange()方法的调用,将value的值赋值给对应字段。2.2任务2的实施
在新增界面为确认图标添加单击事件响应当用户在新增界面中输入姓名、电话等信息时,需要将用户输入的值保存到一个ContactData类型的变量(此处命名为newAccount)对应字段中,在用户点击确认按钮时,将这个newAccount插入到数据库中。使用onClick()方法为确认图标增加单击事件响应,在响应中,调用ContactTable的insertData()方法,将这个ContactData类型的数据插入到数据库29Image($r('app.media.ok'))30.width($r('ponent_size_M'))31.aspectRatio(CommonConstants.FULL_SIZE)32.margin({right:$r('app.float.font_size_L')})33.onClick(()=>{34this.ContactTable.insertData(this.newAccount,(id)=>{35this.newAccount.id=id;36this.accounts.push(this.newAccount);3738router.back();39this.ContactTable.query(0,(result)=>{40this.accounts=result;41for(leti=0;i<(this.accounts.length);i++){42console.log('querysucess:'+this.accounts[i].name);43console.log('querysucess:'+this.accounts[i].phoneNumber);44}4546},true)47})2.2任务2的实施通过本任务,完成了数据模型的创建、数据库的搭建以及查询、新增方法的封装。完成的编码数据库创建数据查询数据新增学到的知识任务小结任务小结任务3显示通讯录联系人列表03任务描述在本任务中,通讯录联系人主界面需要展示已经保存的联系人列表信息(性别图标、姓名、电话)。当用户在新建联系人界面输入新的联系人信息,确认保存以后,能将新联系人追加到主页联系人列表的最后面。任务目的知识目标:(1)熟悉UI组件列表的使用(2)掌握列表条目布局以及数据渲染的方法能力目标:(1)能熟练运用列表和列表条目展示列表素质目标:(1)培养并践行编码规范意识,变量命名可读、格式规范,注释清晰易读。(2)培养自主学习能力,通过阅读文档,学习新知并能在实际项目中运用、解决问题。重难点重点:(1)列表与列表条目布局(2)行项目数据渲染的方法难点:列表行项目数据渲染的方法任务目标及重点难点1、列表组件
List是用来呈现连续、多行相同类型的数据项。多行数据的样式往往相同(也可以不同),每一行称为一个条目。3.1完成任务所需知识清单——列表2、列表布局
(1)设置主轴方向List组件主轴默认是垂直方向,即默认情况下不需要手动设置List方向,就可以构建一个垂直滚动列表。若是水平滚动列表场景,将List的listDirection属性设置为Axis.Horizontal即可实现。listDirection默认为Axis.Vertical,即主轴默认是垂直方向。List(){...}.listDirection(Axis.Horizontal)3.1完成任务所需知识清单——列表
(2)设置交叉轴布局List组件的交叉轴布局可以通过lanes和alignListItem属性进行设置,lanes属性用于确定交叉轴排列的列表项数量,alignListItem用于设置子组件在交叉轴方向的对齐方式。List(){...}.lanes(2)以垂直列表为例,如果将lanes属性设为2,表示构建的是一个两列的垂直列表。lanes的默认值为1,即默认情况下,垂直列表的列数是1。3.1完成任务所需知识清单——列表2、列表布局3、在列表中显示数据
最简单的列表形式中,List静态地创建其列表项ListItem的内容。若列表项是由多个组件元素组成的,则需要将这多个元素组合到一个容器组件内或组成一个自定义组件。1List(){2ListItem(){3Row(){4Image($r('app.media.iconE'))5.width(40)6.height(40)7.margin(10)89Text('小明')10.fontSize(20)11}12}1314ListItem(){15Row(){16Image($r('app.media.iconF'))17.width(40)18.height(40)19.margin(10)2021Text('小红')22.fontSize(20)23}24}25}3.1完成任务所需知识清单——列表迭代列表内容
应用通过数据集合动态地创建列表,使用循环渲染可从数据源中迭代获取数据,并在每次迭代过程中创建相应的组件,降低代码复杂度。1importutilfrom'@ohos.util';23classContact{4key:string=util.generateRandomUUID(true);5name:string;6icon:Resource;78constructor(name:string,icon:Resource){9=name;10this.icon=icon;11}12}3.1完成任务所需知识清单——列表迭代列表内容
ArkTS通过ForEach提供了组件的循环渲染能力。以简单形式的联系人列表为例,将联系人名称和头像数据以Contact类结构存储到contacts数组,使用ForEach中嵌套ListItem的形式来代替多个平铺的、内容相似的ListItem,从而减少重复代码。15@Component16structSimpleContacts{17privatecontacts=[18newContact('小明',$r("app.media.iconA")),19newContact('小红',$r("app.media.iconB")),20...21]2223build(){24List(){25ForEach(this.contacts,(item:Contact)=>{26ListItem(){27Row(){28Image(item.icon)29.width(40)30.height(40)31.margin(10)32Text().fontSize(20)33}34.width('100%')35.justifyContent(FlexAlign.Start)36}37},item=>item.key)38}39.width('100%')40}3.1完成任务所需知识清单——列表
3.1完成任务所需知识清单——状态存储1、状态管理机制当参数改变时,UI作为返回结果,也将进行对应的改变。这些运行时的状态变化所带来的UI的重新渲染,在ArkUI中统称为状态管理机制例如,一段文本默认显示为“HelloWorld”,当用户点击按钮文本变为“HelloArkUI”,也即当用户与应用程序的交互触发了文本状态变更,状态变更引起了UI渲染,UI从“HelloWorld”变更为“HelloArkUI”。
变量必须被装饰器装饰才可以成为状态变量,状态变量的改变会引起UI的渲染刷新。如果不使用状态变量,UI只能在初始化时渲染,后续将不会再刷新。
3.1完成任务所需知识清单——状态存储2、装饰器的两种分类根据状态变量的影响范围,将装饰器可以大致分为:●管理组件拥有状态的装饰器:组件级别的状态管理,可以观察组件内变化,和不同组件层级的变化,但需要唯一观察同一个组件树上,即同一个页面内。●管理应用拥有状态的装饰器:应用级别的状态管理,可以观察不同页面,甚至不同UIAbility的状态变化,是应用内全局的状态管理。从数据的传递形式和同步类型层面看,装饰器也可分为:●只读的单向传递●可变更的双向传递
3.1完成任务所需知识清单——状态存储3、管理应用拥有状态的装饰器
AppStorage由UI框架在应用程序启动时创建,为应用程序UI状态属性提供中央存储,是应用级的全局状态共享。当要在页面之间共享数据时,也即当A页面显示的数据,在B面修改后,A页面能自动更新修改后的数据的场景下就可以采用这种解决方案。(1)观察变化当装饰的数据类型为boolean、string、number类型时,可以观察到数值的变化。当装饰的数据类型为class或者Object时,可以观察到赋值和属性赋值的变化,即Object.keys(observedObject)返回的所有属性。当装饰的对象是array时,可以观察到数组添加、删除、更新数组单元的变化。
3.1完成任务所需知识清单——状态存储3、管理应用拥有状态的装饰器
(2)框架行为
当@StorageLink(key)装饰的数值改变被观察到时,修改将被同步回AppStorage对应属性键值key的属性中。
AppStorage中属性键值key对应的数据一旦改变,属性键值key绑定的所有的数据(包括双向@StorageLink和单向@StorageProp)都将同步修改;
当@StorageLink(key)装饰的数据本身是状态变量,它的改变不仅仅会同步回AppStorage中,还会引起所属的自定义组件的重新渲染。
3.1完成任务所需知识清单——状态存储3、管理应用拥有状态的装饰器
3、管理应用拥有状态的装饰器
第一步:新增联系人列表第二步:列表展示第三步:新建页面数据通步到主页面本任务要在主界面实现联系人列表展示,在新建联系人界面新增的数据在返回主界面时主动追加到列表最后面任务目标实施步骤3.2任务3的实施
1、主页新增联系人列表增加主页面页需要显示的联系人列表accounts,类型为Array<ContactData>;新增ContactTable,以使用其对数据库进行查询操作。在页面显示前,即在aboutToAppear()方法中,从数据库查询所有联系人信息保存到accounts中1import{ImageList}from'../common/CommonConstants';2importContactTablefrom'../common/bean/ContactTable';3importContactDatafrom'../common/bean/ContactData';4importrouterfrom'@ohos.router';5importCommonConstantsfrom'../common/CommonConstants';6@Entry7@Component8structIndex{9@StatesearchText:string='';10@Stateaccounts:Array<ContactData>=[];11privateContactTable=newContactTable();1213searchController:SearchController=newSearchController();1415aboutToAppear(){16this.ContactTable.getRdbStore(()=>{17this.ContactTable.query(0,(result)=>{18this.accounts=result;19},true);20});21}2223build(){24Stack(){25
26
}27}28}3.2任务3的实施
2.列表展示12@Entry3@Component4structIndex{567build(){8Stack(){9Column(){1011
Search({value:this.searchText,placeholder:'要查询的姓名',controller:this.searchController})12.searchButton(CommonConstants.SEARCH_TEXT)13.width('90%')14.borderRadius($r('app.float.radius_size_M'))15.borderWidth($r('app.float.border_size_S'))16.borderColor('#33182431')17.placeholderFont({size:$r('app.float.font_size_M')})18.textFont({size:$r('app.float.font_size_M')})19.backgroundColor(Color.White)20.onChange((searchValue:string)=>{21this.searchText=searchValue;22})23.onSubmit((searchValue:string)=>{24})25}3.2任务3的实施
2、主页显示联系人列表
2.列表展示26Row(){27List({space:CommonConstants.FULL_SIZE}){28ForEach(this.accounts,(item:ContactData)=>{29ListItem(){30Row(){31Image(ImageList[item.accountType])32.width($r('ponent_size_M'))33.aspectRatio(CommonConstants.FULL_SIZE)34.margin({right:$r('app.float.edge_size_MP')})35Text()36.height($r('ponent_size_SM'))37.fontSize($r('app.float.font_size_M'))38.margin({right:$r('app.float.edge_size_MP')})39.width('20%')40Text(item.phoneNumber)41.height($r('ponent_size_SM'))42.fontSize($r('app.float.font_size_M'))43.margin({left:'50'})44}45.width(CommonConstants.FULL_WIDTH)46.padding({left:$r('app.float.edge_size_M'),right:$r('app.float.edge_size_M')})47}3.2任务3的实施
2.列表展示48.width(CommonConstants.FULL_WIDTH)49.height($r('ponent_size_LM'))50.onClick(()=>{5152})53})54}55.width(CommonConstants.FULL_WIDTH)56.borderRadius($r('app.float.radius_size_L'))57.backgroundColor(Color.White)58}59.width(CommonConstants.FULL_WIDTH)60.padding({left:$r('app.float.edge_size_M'),right:$r('app.float.edge_size_M')})61.margin({top:$r('app.float.edge_size_SM')})3.2任务3的实施
3、修改Accounts数据状态类型
(1)
在新建页面新增了一条记录以后,不仅要把新联系人插入到数据库,也需要将这条联系人信息增加到主页的accounts;
(2)
在页面第一次读取数据库所有联系人信息时,将这个结果accounts保存为应用级数据共享,这样从新增页面保存完回到主页面时,主页面就能实时显示最新加入的联系人了。12structIndex{3@StorageLink('varA')accounts:Array<AccountData>=[];4修改Index.ets修改AddPage.ets1structAddPage{2@StorageLink('varA')accounts:Array<AccountData>=[];34build(){5Column(){6Row(){7Image($r('app.media.cancel'))3.2任务3的实施修改Index.ets通过本任务,完成了从数据库读取联系人信息,再主页面数据列表的展示。完成的编码List布局循环渲染学到的知识任务小结任务小结任务4查看联系人详情04任务描述当用户在在联系人主界面的列表中点击任意一联系人条目,将跳转到联系人详情界面。当点击详情界面的返回箭头图标时,将返回到联系人主页面。任务目的知识目标:(1)掌握跳转时参数的传递与解析能力目标:(1)能熟练传递参数与解析参数素质目标:(1)培养并践行编码规范意识,变量命名可读、格式规范,注释清晰易读。(2)培养自主学习能力,通过阅读文档,学习新知并能在实际项目中运用、解决问题。重难点重点:掌握页面跳转时参数的传递与解析难点:掌握页面跳转时参数的传递与解析
任务目标及重点难点任务目标及重点难点路由参数的传递与解析4.1知识清单
如果在跳转时需要传递一些数据给目标页,则可以在调用Router模块的方法时,添加一个params属性,并指定一个对象作为参数。1classDataModelInfo{2age:number;3}45classDataModel{6id:number;7info:DataModelInfo;8}9
10functiononJumpClick():void{1112letparamsInfo:DataModel={13id:123,14info:{15age:2016}17};1819router.pushUrl({20url:'pages/Detail',//目标url21params:paramsInfo//添加params属性,传递自定义参数22},(err)=>{23if(err){24console.error(`InvokepushUrlfailed,codeis${err.code},messageis${err.message}`);25return;26}27('InvokepushUrlsucceeded.');28})29}4.1知识清单
在目标页中,可以通过调用Router模块的getParams()方法来获取传递过来的参数。例如:1constparams=router.getParams();//获取传递过来的参数对象2constid=params['id'];//获取id属性的值3constage=params['info'].age;//获取age属性的值4.1知识清单第一步:新建联系人详情页面第二步:联系人列表主页面设置到详情页面的跳转第三步:详情页面解析路由传递的参数本任务需要从联系人主页面跳转到联系人详情界面,可以用router跳转实现。因详情界面需要展示性别、姓名、点哈,所以被点击的联系人信息需要从主页传递到详情界面。任务目标实施步骤4.2任务4的实施
1、新建联系人详情页面在src>main>ets>pages中创建新页面DetailPage.ets。与新建联系人页面相似,由5行垂直排列而成,每行内部行线性排列4.2任务4的实施
2、在联系人列表主页面设置单击事件监听,一旦监听到用户点击事件,则跳转到新页面并被点击的联系人对象作为参数传递到新页面123@Entry4@Component5structIndex{6 7 Row(){8List({space:CommonConstants.FULL_SIZE}){9ForEach(this.accounts,(item:ContactData)=>{10ListItem(){11Row(){121314}15.width(CommonConstants.FULL_WIDTH)16.padding({left:$r('app.float.edge_size_M'),right:$r('app.float.edge_size_M')})17}18.width(CommonConstants.FULL_WIDTH)19.height($r('ponent_size_LM'))20.onClick(()=>{21router.pushUrl({url:'pages/DetailPage',params:{contactData:item}})22})23})24 }25 }26}27 4.2任务4的实施
3、新建联系人详情页面解析参数在联系人详情页面解析主页面传递过来的联系人信息,将其填入对应的位置。1@Entry2@Component3structDetailPage{4//@ts-ignore5privatecontactItem:ContactData=router.getParams()['contactData']6gender:string=''7@Statemessage:string='联系人详情'8privateAccountTable=newContactTable();9build(){10Column(){11 12 }13
}14
}4.2任务4的实施本节实现了联系人详情界面的编写,以及从主界面到详情界面的跳转、参数传递,再详情界面的路由参数解析及展现。完成的编码路由参数的传送路由参数的解析学到的知识任务小结任务小结——感谢观看——THANKS长沙民政职业技术学院鸿蒙应用开发项目四开发相册本项目为手机用户开发一个相册,这个相册即要有一般手机都有的基本相册功能,又要有基于分布式能力的照片共享功能。CONTENTS目录任务一完成主界面UI设计和媒体访问权限的申请1任务二
读取并展示媒体库的图片2掌握鸿蒙系统权限申请方法;掌握系统多媒体数据访问方法;掌握弹性布局的使用;掌握常用组件的使用;掌握页面状态管理和渲染控制技术知识目标能进行项目的需求分析和功能设计;能使用各种布局、组件、系统能力开发复杂应用;能力目标培养项目分析与设计能力;培养运用多种技术解决复杂问题的能力。素养目标教学目标场景描述主界面在主界面中以标签页的形式提供“照片”、“相册”两大功能,默认显示“照片”标签页。如果有照片,显示如图(a)的界面,如果没有照片,显示如图4-1(b)所示的界面。系统中没有照片时:如果没有照片,显示如图(b)所示的界面应用启动时:“照片”标签页从手机存储中获取所有图片,将这些图片按日期组织在一起,以日期倒序方式将这些图片的缩略图显示在列表中,每日的图片水平方向显示,一行显示不下换行显示,如图(a)。本项目为手机用户开发一个简易相册。利用鸿蒙OS提供的媒体访问能力查询手机中的相册和图片信息,并利用强大的UI组件展示这些数据。场景描述显示图片明细从“照片”或“相册”的图片列表中点击任何一张缩略图时,调用“显示原图”界面将原图显示出来
本项目为手机用户开发一个简易相册。利用鸿蒙OS提供的媒体访问能力查询手机中的相册和图片信息,并利用强大的U
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 3.1 大气的组成和垂直分层1 课件上学期地理湘教版(2019)必修第一册
- 押大题02地球运动-2023年中考地理之考前押大题
- 人教部编版八年级语文上册《国行公祭为佑世界和平》公开示范教学课件
- 三年级上册生活生命与安全教案
- 安全教育主题班会教案多篇
- 活鱼冷链运输保障协议
- 4S店拆旧合同模板
- 2024年郑州考客运资格证需要什么东西
- 2024年全新联名品牌合作协议
- 2024年三方租房协议书
- 道路开口施工方案
- 咖啡厅室内设计PPT
- 北师大一年级数学上册期中测试卷及答案
- 小学二年级上册美术课件-5.17漂亮的钟-岭南版(14张)ppt课件
- 苏教版六年级上册音乐教案全册
- 江苏某市政道路地下通道工程深基坑支护及土方开挖施工专项方案(附图)
- 生物校本教材—生活中的生物科学
- 北京市建筑施工起重机械设备管理的若干规定
- 新建时速200公里客货共线铁路设计暂行规定
- 边沟、排水沟、截水沟施工方案(完整版)
- 实行特殊工时工作制实施方案
评论
0/150
提交评论