赞
踩
本篇Codelab基于用户首选项,实现了备忘录新增、更新、删除以及查找等功能。效果如图所示:
完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:
[获取OpenHarmony系统版本]:标准系统解决方案(二进制)。以3.2 Release版本为例:
搭建烧录环境。
gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md
点击或者复制转到参考。搭建开发环境。
鸿蒙HarmonyOS与OpenHarmony开发籽料mau123789添加v可直接拿
本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在gitee中提供。
├──entry/src/main/ets // 代码区 │ ├──common │ │ ├──constants │ │ │ ├──CommonConstants.ets // 常量类 │ │ │ └──StyleConstants.ets // 样式常量类 │ │ └──utils │ │ ├──Format.ets // 日期格式化函数 │ │ └──Logger.ets // 日志打印类 │ ├──entryability │ │ └──EntryAbility.ts // 程序入口类 │ ├──model │ │ └──NotesDataModel.ets // 备忘录方法类 │ ├──pages │ │ ├──NoteHomePage.ets // 备忘录主页面(列表页) │ │ └──NotesDetail.ets // 备忘录详情页 │ ├──view │ │ ├──BottomBar.ets // 备忘录编辑页底部栏 │ │ ├──ConfirmDialog.ets // 自定义弹窗 │ │ └──MemoItem.ets // 自定义备忘录列表组件 │ └──viewmodel │ └──NotesInfoViewModel.ets // 备忘录默认数据实体 └──entry/src/main/resources // 资源文件目录
在这个章节中,需要实现备忘录数据的初始化,并且通过List组件将其渲染出来。效果如图所示:
在saveDefaultData方法中先通过getPreferences方法获取preferences实例,然后调用has方法查找数据库中是否存在“noteIdArr”这个key值,如果不存在调用实例的put方法将noteIdArr以及备忘录数据写入,最后通过flush方法进行数据持久化。
// NotesDataModel.ets import dataStorage from '@ohos.data.preferences'; ... class NotesDataModel { private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; /** * 写入备忘录数据. */ async saveDefaultData() { try { let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME); let isExist = await preferences.has(CommonConstants.PREFERENCE_NOTE_KEY); if (!isExist) { preferences.put(CommonConstants.PREFERENCE_NOTE_KEY, JSON.stringify(noteIdArray)); preferences.flush(); notesItemArr.forEach((item: NotesInfoBean) => { let notes: NotesInfoBean = item; let res = preferences.put(item.noteId, JSON.stringify(notes)); preferences.flush(); res.then(() => { Logger.info('Put the value successfully.' + item.noteId); }).catch((err: Error) => { Logger.error(`Put the value failed with err: ${err}`); }) }) } } catch (err) { Logger.error(`Failed to get preferences. Error = ${err}`); } } /** * 基于笔记类型获取对应备忘录数据. * * @param flag the folder type. * @param allNotes all of notes. * @returns subNotes. */ getSelectNotes(flag: FolderType, allNotes: Array<NotesInfoBean>): Array<NotesInfoBean> { return allNotes.filter((item: NotesInfoBean) => item.folder === flag); } }
在NoteHomePage.ets文件中调用saveDefaultData函数先将本地数据写入数据库,再调用实例的get方法进行查询操作。
// NoteHomePage.ets import dataStorage from '@ohos.data.preferences'; ... @Entry @Component struct NoteHomePage { @State folderType: Resource = $r('app.string.notes_all'); @State allNotes: Array<NotesInfoBean> = []; @State selectNotes: Array<NotesInfoBean> = this.allNotes.sort(); private context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext; ... build() { Column() { ... List({ space: StyleConstants.MEMO_LIST_SPACE }) { ForEach(this.selectNotes, (item: NotesInfoBean) => { ListItem() { MemoItem({ noteItem: item }) } }, (item: NotesInfoBean) => JSON.stringify(item)) } .margin({ top: $r('app.float.list_container_margin') }) .height(StyleConstants.NOTE_CONTENT_HEIGHT) .width(StyleConstants.FULL_WIDTH) } .backgroundColor($r('app.color.page_background')) .height(StyleConstants.FULL_HEIGHT) } onPageShow() { this.getAllNotes(); } async getAllNotes() { await NotesDataModel.saveDefaultData(); try { let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME); let noteIds = await preferences.get(CommonConstants.PREFERENCE_NOTE_KEY, ''); while (this.allNotes.length >= 1) { this.allNotes.pop(); } JSON.parse(noteIds.toString()).forEach(async (item: NotesInfoBean) => { let note = await preferences.get(item.noteId, ''); this.allNotes.push(JSON.parse(note.toString())); }) } catch (err) { Logger.error('Get the value of noteIdArr failed with err:', err); } } }
此章节介绍新增备忘录功能,点击列表页右上角加号进入编辑页,支持输入标题、备忘录内容以及添加图片。效果如图所示:
首先在列表页NoteHomePage.ets中添加跳转逻辑,设置路由参数params,其中operationType字段代表此次操作是新增还是修改。
// NoteHomePage.ets Navigator({ target: 'pages/NotesDetail', type: NavigationType.Replace }) { Row() { Image($rawfile('ic_title_add.svg')) ... } .margin({ right: $r('app.float.note_add_margin') }) } .params({ notesInfo: { 'noteId': new Date().getTime().toString(), 'title': '', 'folder': FolderType.Personal, 'content': '', 'imageArr': [], 'time': new Date().toTimeString().split(' ')[0], 'isFavorite': false }, operationType: CommonConstants.ADD_NOTE })
进入编辑页NotesDetail.ets后可以输入标题、内容以及选择对应的笔记类型等,确认保存后备忘录数据实时更新。
// NotesDetail.ets build() { ... TextInput({ text: this.notesInfo.title != '' ? this.notesInfo.title : '', placeholder: this.notesInfo.title != '' ? '' : $r('app.string.note_title_placeholder') }) ... .onChange((value: string) => { if (value !== this.notesInfo.title) { this.notesInfo.title = value; this.isDataChanged = true; } }) ... TextArea({ text: this.notesInfo.content !== '' ? this.notesInfo.content : '', placeholder: this.notesInfo.content !== '' ? '' : $r('app.string.note_content_placeholder') }) .onChange((value: string) => { if (value !== this.notesInfo.content) { this.notesInfo.content = value; this.isDataChanged = true; } }) ... } onBackPress() { if (this.isDataChanged || this.notesFolder !== this.notesInfo.folder || this.isCollectChange) { this.saveDialogController.open(); } else { router.replaceUrl({ url: 'pages/NoteHomePage' }); } return true; } // ConfirmDialog.ets if (this.type === CommonConstants.SAVE_DIALOG) { this.confirm = async () => { let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME); // 保存备忘录数据实时更新 if (this.operationType === CommonConstants.ADD_NOTE) { this.noteIdArray.push(new NoteIdBean(this.notesInfo.noteId)); preferences.put(CommonConstants.PREFERENCE_NOTE_KEY, JSON.stringify(this.noteIdArray)); preferences.flush(); } let newNotes = this.notesInfo; await preferences.put(this.notesInfo.noteId, JSON.stringify(newNotes)); await preferences.flush(); router.replaceUrl({ url: 'pages/NoteHomePage' }); } }
此章节介绍更新数据库操作,与新增备忘录逻辑类似。效果如图所示:
首先在NotesDetail.ets中设置isDataChange和isCollectChange属性,来表示对应noteId的备忘录数据是否已更改。如果isDataChange或者isCollectChange为true表示已更改,在返回列表页时会拉起确认弹窗,确认保存后执行put方法去更改备忘录数据。
// NotesDetail.ets build() { Column() { ... Stack({ alignContent: Alignment.Bottom }) { Scroll(this.scroller) { Column() { TextInput({ text: this.notesInfo.title != '' ? this.notesInfo.title : '', placeholder: this.notesInfo.title != '' ? '' : $r('app.string.note_title_placeholder') }) ... .onChange((value: string) => { if (value !== this.notesInfo.title) { this.notesInfo.title = value; this.isDataChanged = true; } }) ... TextArea({ text: this.notesInfo.content !== '' ? this.notesInfo.content : '', placeholder: this.notesInfo.content !== '' ? '' : $r('app.string.note_content_placeholder') }) .onChange((value: string) => { if (value !== this.notesInfo.content) { this.notesInfo.content = value; this.isDataChanged = true; } }) ... } } ... BottomBar({ imageArr: $imageArr, notesInfo: $notesInfo, operationType: $operationType, noteIdArray: $noteIdArray, isDataChanged: $isDataChanged }) } ... } .height(StyleConstants.FULL_HEIGHT) .backgroundColor($r('app.color.white_color')) } ... onBackPress() { if (this.isDataChanged || this.notesFolder !== this.notesInfo.folder || this.isCollectChange) { this.saveDialogController.open(); } else { router.replaceUrl({ url: 'pages/NoteHomePage' }); } return true; } // BottomBar.ets // 点击收藏 this.clickCollect = () => { this.notesInfo.isFavorite = !this.notesInfo.isFavorite; this.isFavorite = !this.isFavorite; this.collectImgSrc = this.notesInfo.isFavorite ? 'ic_bottom_star_selected.svg' : 'ic_bottom_star_normal.svg'; } ... // 点击插入图片 this.clickAddPicture = () => { this.imageSrc = this.chooseImage(); if (this.imageSrc === '') { prompt.showToast({ message: 'Not anymore pictures' }); } else { this.imageArr = this.notesInfo.imageArr; this.imageArr.push(this.imageSrc); this.isDataChanged = true; } } // ConfirmDialog.ets if (this.type === CommonConstants.SAVE_DIALOG) { this.confirm = async () => { let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME); if (this.operationType === CommonConstants.ADD_NOTE) { this.noteIdArray.push(new NoteIdBean(this.notesInfo.noteId)); preferences.put(CommonConstants.PREFERENCE_NOTE_KEY, JSON.stringify(this.noteIdArray)); preferences.flush(); } // 保存备忘录数据实时更新 let newNotes = this.notesInfo; await preferences.put(this.notesInfo.noteId, JSON.stringify(newNotes)); await preferences.flush(); router.replaceUrl({ url: 'pages/NoteHomePage' }); } }
上述章节介绍了数据库的新增与更新,此章节来介绍删除操作。效果如图所示:
在BottomBar.ets中点击删除按钮,弹出自定义弹窗选择“是否删除”。在ConfirmDialog.ets中添加删除逻辑,删除操作会调用preferences实例的delete方法,将对应noteId的备忘录数据从数据库中删除,最后执行实例的flush方法实现持久化。
// BottomBar.ets export default struct BottomBar { ... deleteDialogController: CustomDialogController = new CustomDialogController({ builder: ConfirmDialog({ notesInfo: $notesInfo, operationType: $operationType, noteIdArray: $noteIdArray, type: CommonConstants.DELETE_DIALOG }), autoCancel: true, alignment: DialogAlignment.Bottom, offset: { dx: $r('app.float.dialog_offset_x'), dy: $r('app.float.dialog_margin_bottom') } }); ... build() { ... Column() { Image($r('app.media.ic_bottom_delete')) .width($r('app.float.ic_bottom_picture_size')) .aspectRatio(1) Text($r('app.string.delete_note')) .fontSize($r('app.float.font_size_smallest')) .margin({ top: $r('app.float.bottom_txt_margin') }) } .onClick(() => { this.clickDelete = () => { if (this.operationType === CommonConstants.MODIFY_NOTE) { this.deleteDialogController.open(); } else { prompt.showToast({ message: 'The addition operation cannot be deleted' }); } } this.clickDelete(); }) ... } ... } // ConfirmDialog.ets if (this.type === CommonConstants.SAVE_DIALOG) { ... } else { // 删除备忘录数据 this.confirm = async () => { let preferences = await dataStorage.getPreferences(this.context, CommonConstants.PREFERENCE_INSTANCE_NAME); await preferences.delete(this.notesInfo.noteId); await preferences.flush(); router.replaceUrl({ url: 'pages/NoteHomePage' }); } } this.confirm(); })
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。