<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

HarmonyOS開發實例:【手機備忘錄】

jf_46214456 ? 來源:jf_46214456 ? 作者:jf_46214456 ? 2024-04-18 21:40 ? 次閱讀

介紹

本篇Codelab基于用戶首選項,實現了備忘錄新增、更新、刪除以及查找等功能。效果如圖所示:

相關概念

  • [用戶首選項]:提供Key-Value鍵值型的數據處理能力,應用持久化輕量級數據,并對其修改和查詢。
  • [Navigator]:路由容器組件,支持路由跳轉以及子組件嵌入。

環境搭建

軟件要求

  • [DevEco Studio]版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 開發板類型:[潤和RK3568開發板]。
  • OpenHarmony系統:3.2 Release。

環境搭建

完成本篇Codelab我們首先要完成開發環境的搭建,本示例以RK3568開發板為例,參照以下步驟進行:

  1. [獲取OpenHarmony系統版本]:標準系統解決方案(二進制)。以3.2 Release版本為例:
  2. 搭建燒錄環境。
    1. [完成DevEco Device Tool的安裝]
    2. [完成RK3568開發板的燒錄]
    3. 鴻蒙開發指導文檔:[gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md]
  3. 搭建開發環境。
    1. 開始前請參考[工具準備],完成DevEco Studio的安裝和開發環境配置。
    2. 開發環境配置完成后,請參考[使用工程向導]創建工程(模板選擇“Empty Ability”)。
    3. 工程創建完成后,選擇使用[真機進行調測]。

搜狗高速瀏覽器截圖20240326151450.png

代碼結構解讀

本篇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();
})

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 鴻蒙
    +關注

    關注

    55

    文章

    1769

    瀏覽量

    42153
  • HarmonyOS
    +關注

    關注

    79

    文章

    1878

    瀏覽量

    29335
  • OpenHarmony
    +關注

    關注

    23

    文章

    3380

    瀏覽量

    15194
收藏 人收藏

    評論

    相關推薦

    高顏值智能備忘錄:不再遺忘任何要事

    摸出手機,在屏幕上找出備忘錄,打字,糾錯,排版...感覺好心塞...或者某天你在跑步,突然想起要給明天生日的女朋友買禮物,你在心里反復提醒,然后...跪了一晚上榴蓮...面對這些情況,小編特別想給大家
    發表于 05-19 21:48

    PostgreSQL操作備忘錄

    PostgreSQL 操作備忘錄
    發表于 05-23 08:48

    【軟通動力】HarmonyOS 手機通訊開發 實驗指導手冊 V 1.0

    人員開發技能前置要求,良好的 Java 基礎和 sql 基礎能力; 2. 配置好 HarmonyOS 移動應用開發環境 3. 完成鴻蒙手機通訊
    發表于 06-17 14:41

    UDS診斷命令備忘錄

    UDS實踐性強,邏輯復雜,很多服務非要體驗過一次才能理解,導致包括我在內的初學者感覺晦澀難懂,不明覺厲,因此將自己的理解寫下來、整理下來,與君共勉。零、UDS診斷命令備忘錄一、簡介UDS
    發表于 08-26 16:09

    怎樣去搭建一種基于XR806的開源桌面備忘錄

    本人計劃懟一個開源桌面備忘錄/天氣預報/相冊的項目基于XR806,同時學習鴻蒙操作系統獲得暈哥贈送的開發板和芯片,目前處于環境搭建階段看起來這個芯片玩的人比較少,目前遇到了問題,不知道如何解決,希望
    發表于 12-28 06:52

    keil5MDK和eplan2.7安裝備忘錄相關資料分享

    備忘錄是防止以后安裝的時候忘記步驟和主要問題。keil5安裝我第一次使用的是軟件安裝管家的安裝包,安完以后發現注冊碼一直弄不上,芯片庫里邊也沒有STM32的芯片。然后找到大二時候電子工藝實習
    發表于 01-10 07:06

    戴姆勒與百度簽署諒解備忘錄

    7月25日,奔馳母公司戴姆勒與百度簽署諒解備忘錄,深化雙方在自動駕駛和車聯網等領域的戰略合作。
    的頭像 發表于 07-28 09:53 ?2539次閱讀

    怎樣將蘋果備忘錄筆記Notes“安裝”到Win10上

    用iPhone、iPad的朋友一直有這樣一個困惑,在手機平板上記錄的蘋果Notes備忘錄筆記,要怎么在電腦上查看?
    的頭像 發表于 03-31 16:22 ?6609次閱讀

    慧榮科技與江波龍簽署策略合作備忘錄

    近日,慧榮科技與江波龍簽署策略合作備忘錄,旨在提升雙方在手機存儲市場的市場份額和綜合產品競爭力,形成協同成長的深度合作伙伴關系。
    的頭像 發表于 07-14 11:13 ?850次閱讀

    設計模式:備忘錄設計模式

    備忘錄設計模式(Memento Design Pattern)是一種行為型設計模式,它的主要目的是在不破壞對象封裝性的前提下,捕捉和保存一個對象的內部狀態
    的頭像 發表于 06-06 11:19 ?624次閱讀

    設計模式行為型:備忘錄模式

    備忘錄模式(Memento Pattern)保存一個對象的某個狀態,以便在適當的時候恢復對象。備忘錄模式屬于行為型模式。
    的頭像 發表于 06-07 11:16 ?605次閱讀
    設計模式行為型:<b class='flag-5'>備忘錄</b>模式

    新思科技同越南政府簽署諒解備忘錄

    在越南總理范明政訪美期間,新思科技與越南國家創新中心(nic)簽署了關于培養越南集成電路設計人才的諒解備忘錄,支持nic成立芯片設計孵化中心。另外,新思科技與越南信息通訊部下屬的信息通信技術產業公司簽訂了支援越南半導體產業發展的諒解備忘錄。
    的頭像 發表于 09-20 10:56 ?1277次閱讀

    實踐GoF的23種設計模式:備忘錄模式

    相對于代理模式、工廠模式等設計模式,備忘錄模式(Memento)在我們日常開發中出鏡率并不高,除了應用場景的限制之外,另一個原因,可能是備忘錄模式
    的頭像 發表于 11-25 09:05 ?286次閱讀
    實踐GoF的23種設計模式:<b class='flag-5'>備忘錄</b>模式

    江汽與華為簽訂合作備忘錄 發力鴻蒙

    江汽與華為簽訂合作備忘錄進一步深化雙方合作;共同發力鴻蒙,江汽與華為將以OpenHarmony為底座的HarmonyOS啟動鴻蒙原生應用開發;為用戶提供更智能的體驗。
    的頭像 發表于 03-27 16:00 ?724次閱讀

    容百科技宣布與SK On簽訂《合作備忘錄

    本周,容百科技宣布與SK On簽訂《合作備忘錄》,雙方將圍繞三元和磷酸錳鐵鋰正極開展深度合作。
    的頭像 發表于 03-29 09:56 ?171次閱讀
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>