HarmonyOS 評論回復彈窗最佳實踐

HarmonyOS 評論回復彈窗最佳實踐

前言

在移動應用開發中,評論回復功能是一個常見且重要的交互場景。本文將詳細介紹如何在 HarmonyOS 中實現一個功能完善的評論回復彈窗,包括彈窗選型、富文本編輯、軟鍵盤適配等關鍵技術點。

功能概述

我們要實現的評論回復彈窗具備以下功能:

  • 支持文字輸入
  • 支持表情選擇
  • 支持@好友功能
  • 軟鍵盤與表情面板無縫切換
  • 良好的用戶體驗

技術選型分析

彈窗組件選型

在開始開發之前,我們需要選擇合適的彈窗實現方案。HarmonyOS 提供了多種彈窗實現方式,我們對比了三種主要方案:

通過對CustomDialog自定義彈窗、bindSheet半模態彈窗、Navigation Dialog三種彈窗方案進行嘗試,發現自定義彈窗和半模態彈窗有一定規格限制,會產生一些無法避免的問題,最終選用Navigation Dialog方案實現評論模塊彈窗。以下對三種方案優劣勢進行一個詳細的說明。

方案一:CustomDialog 自定義彈窗

CustomDialog 是 HarmonyOS 提供的標準彈窗組件。

優勢:

  • ? 開箱即用,無需實現彈窗交互邏輯
  • ? 自動避讓軟鍵盤,使用簡單
  • ? 系統級組件,穩定性好

劣勢:

  • ? 軟鍵盤避讓行為無法自定義配置
  • ? 表情面板切換時會出現短暫的布局跳動
  • ? 無法獲取軟鍵盤動畫信息,難以實現平滑過渡

問題演示: 當用戶點擊表情按鈕時,軟鍵盤收起過程中表情面板會短暫顯示在錯誤位置,影響用戶體驗。

CustomDialog 問題演示

注意: PromptAction.openCustomDialog 與 CustomDialog 效果相同,存在同樣的問題。

方案二:bindSheet 半模態彈窗

bindSheet 是 HarmonyOS 提供的半模態彈窗組件,常用于底部彈出的交互場景。

優勢:

  • ? 開箱即用,無需實現彈窗交互邏輯
  • ? 可以解決 CustomDialog 中的軟鍵盤頂起問題
  • ? 支持手勢拖拽,交互體驗較好

劣勢:

  • ? 高度自適應時內部滾動行為難以控制
  • ? 即使禁用拖拽條,仍可拖動彈窗
  • ? 拖動過程中可能暴露表情面板,影響視覺效果

問題演示: 當禁用拖拽條后,用戶仍可以拖動彈窗,這會在拖動過程中暴露底層的表情面板區域。

bindSheet 問題演示

方案三:Navigation Dialog(推薦方案)

Navigation Dialog 基于 Navigation 路由系統實現的彈窗方案。

優勢:

  • ? 完美解決前兩種方案的所有問題
  • ? 基于路由棧管理,彈窗與 UI 完全解耦
  • ? 可精確控制軟鍵盤避讓行為
  • ? 支持復雜的彈窗層級管理

劣勢:

  • ? 需要手動實現遮罩層和點擊關閉邏輯
  • ? 開發復雜度相對較高

重要提醒: Navigation Dialog 的 z 軸層級較低,如果項目中同時使用多種彈窗方案,建議統一使用 Navigation Dialog 以避免層級沖突。

最終選擇

經過綜合對比,我們選擇 Navigation Dialog 作為最終方案,主要原因:

  1. 完美的軟鍵盤控制:可以精確控制軟鍵盤避讓行為,實現平滑的切換動畫
  2. 良好的架構設計:基于路由的設計更符合現代應用架構理念
  3. 可擴展性強:便于后續功能擴展和維護

雖然開發復雜度稍高,但帶來的用戶體驗提升是值得的。

編輯區域組件選型

評論輸入框需要支持多種內容類型:

  • 📝 文字輸入:普通文本內容
  • 😊 表情符號:圖片形式的表情
  • 👥 @好友功能:特殊樣式的用戶標簽
RichEditor 組件介紹

對于這種圖文混排的需求,HarmonyOS 提供的 RichEditor 組件是最佳選擇。它支持:

  • 富文本編輯:文字、圖片、自定義組件混合編輯
  • 靈活的內容管理:通過不同的 Span 類型管理內容
  • 豐富的交互事件:輸入、刪除、選擇等事件監聽
內容類型與實現方法

RichEditor 提供了三種主要的內容添加方法:

內容類型實現方法用途
文字addTextSpan普通文本內容
圖片addImageSpan表情圖片
自定義組件addBuilderSpan@好友標簽

術語說明: 為方便理解,我們將通過這三種方法添加的內容分別稱為 textSpanimageSpanbuilderSpan

@好友功能實現方案對比

對于 @好友功能,我們有兩種實現方案可選:

方案一:使用 addTextSpan 實現

將 @好友 作為普通文本處理。

問題分析:

  • ? 文本合并問題:前后輸入的文字會自動與 @好友 文本合并,破壞標簽的獨立性
  • ? 交互復雜:需要手動處理光標定位和整體刪除邏輯
  • ? 數據關聯困難:只能獲取昵稱文本,無法關聯用戶的完整信息(如 ID、頭像等)
方案二:使用 addBuilderSpan 實現(推薦)

將 @好友 作為自定義組件處理。

優勢分析:

  • ? 獨立性好:不會與前后文字合并,保持標簽完整性
  • ? 交互簡單:系統自動處理光標和刪除邏輯
  • ? 數據豐富:可以維護完整的用戶信息,便于后續處理

注意事項:

  • 需要手動維護 builderSpan 的信息,但這也帶來了更大的靈活性
最終選擇

我們選擇 addBuilderSpan 方案,主要考慮:

  1. 更好的用戶體驗:@好友 標簽作為整體,交互更自然
  2. 更強的擴展性:可以輕松添加頭像、樣式等豐富元素
  3. 更可靠的數據管理:完整的用戶信息便于業務處理

核心功能實現

1. 彈窗顯示實現

功能流程

評論彈窗的顯示流程如下:

  1. 用戶在視頻頁面點擊消息按鈕
  2. 彈出評論列表頁面
  3. 用戶點擊寫評論按鈕
  4. 彈出評論輸入彈窗

彈窗顯示流程

技術實現要點
1. Navigation 配置
// 主頁面 Navigation 配置
Navigation() {// 頁面內容
}
.mode(NavigationMode.Stack)  // 設置為棧模式
.hideTitleBar(true)         // 隱藏標題欄
2. 彈窗組件結構
// 彈窗頁面組件
@Component
struct CommentDialog {build() {NavDestination() {Stack() {// 遮罩層Column().width('100%').height('100%').backgroundColor('rgba(0,0,0,0.5)').onClick(() => {// 點擊遮罩關閉彈窗router.back()})// 彈窗內容Column() {// 評論輸入組件}.backgroundColor(Color.White).borderRadius(12)}}.mode(NavDestinationMode.DIALOG)  // 設置為彈窗模式.expandSafeArea([SafeAreaType.KEYBOARD])  // 不避讓軟鍵盤}
}
3. 關鍵配置說明
配置項作用重要性
NavigationMode.Stack啟用路由棧管理???
NavDestinationMode.DIALOG設置為彈窗類型???
expandSafeArea([SafeAreaType.KEYBOARD])不避讓軟鍵盤???
遮罩層點擊事件提供關閉交互??
彈窗管理策略
  • 彈出:通過 router.pushUrl() 進入路由棧
  • 關閉:通過 router.back() 退出路由棧
  • 層級:路由棧的順序決定彈窗層級關系

2. 軟鍵盤和表情面板切換適配

功能需求

在評論彈窗中,用戶需要能夠在軟鍵盤和表情面板之間無縫切換,提供良好的輸入體驗。

軟鍵盤表情切換

技術實現方案
1. 自定義鍵盤控制

本文選擇自定義鍵盤來控制軟鍵盤和表情面板的切換:

  • 顯示表情面板:設置 RichEditor.customKeyboard 為表情面板組件的構建函數 EmojiKeyboard
  • 顯示軟鍵盤:設置 customKeyboard 屬性為 undefined
  • 焦點管理:通過這種方式切換時無需手動處理 RichEditor 焦點
2. 高度適配策略

為保證切換過程中評論模塊整體高度不變,需要實現以下邏輯:

軟鍵盤高度監聽:

// 監聽軟鍵盤高度變化
window.on('keyboardHeightChange', (height: number) => {if (height > 0) {this.keyboardHeight = height;}
});

高度計算規則:

  • 表情面板高度 = 常用表情列表高度 + 軟鍵盤高度
  • 占位元素高度 = 當前顯示組件的高度(軟鍵盤或表情面板)
3. 布局適配實現

由于彈窗設置了不避讓軟鍵盤,需要通過占位元素來控制布局:

// 占位元素高度控制
@State placeholderHeight: number = 0;// 切換到軟鍵盤時
this.placeholderHeight = this.keyboardHeight;// 切換到表情面板時  
this.placeholderHeight = this.emojiPanelHeight + this.keyboardHeight;
注意事項
  • ?? 內存管理:組件銷毀前必須取消鍵盤高度監聽事件
  • ?? 高度變化:軟鍵盤高度可能被用戶手動調整,需要實時監聽
  • ?? 時序控制:切換過程中要確保高度設置的時序正確

3. @好友功能實現

功能概述

@好友功能允許用戶在評論中提及其他用戶,被@的用戶會收到通知,這是社交應用中的重要功能。

觸發方式

用戶可以通過兩種方式觸發@好友功能:

  1. 點擊@按鈕:直接點擊編輯區域的@按鈕
  2. 鍵盤輸入:在軟鍵盤上輸入@符號

實現流程
1. 觸發@功能

點擊@按鈕時:

// 添加@符號并顯示好友列表
this.richEditorController.addTextSpan('@', {style: {fontColor: Color.Blue}
});
this.showFriendList = true;

監聽鍵盤輸入:

// 監聽輸入事件,統一處理@符號
.aboutToIMEInput((value: RichEditorInsertValue) => {if (value.insertValue === '@') {// 觸發@好友邏輯this.showFriendList = true;return true; // 阻止默認輸入}return false;
})

通過 RichEditorController.addTextSpan 添加@符號,并顯示好友列表。同時監聽 RichEditor.aboutToIMEInput 事件,統一處理點擊@按鈕和鍵盤輸入@的邏輯。

在好友列表中點擊好友頭像時,通過RichEditorController.getSpans可以獲取光標前一個span的內容,若光標前一個span是內容為@的textSpan,則先刪除,然后通過RichEditorController.addBuilderSpan將“@[好友昵稱]”以指定的樣式作為一個整體添加到編輯區域中。

4. 內容刪除功能

功能需求

在刪除@好友內容時,需要實現智能刪除:第一次點擊刪除鍵時選中整個@好友組件,第二次點擊時整體刪除,而不是逐字符刪除。

刪除功能演示

實現方案
// 監聽刪除事件
.aboutToDelete((value: RichEditorDeleteValue) => {// 獲取要刪除的span信息const spans = this.richEditorController.getSpans(value.offset, value.offset + value.length);if (spans.length > 0) {const span = spans[0];// 如果是builderSpan(@好友)且未被選中if (span.spanType === 'builderSpan' && !this.isSpanSelected(span)) {// 第一次刪除:選中整個@好友組件this.richEditorController.setSelection(span.start, span.end);return false; // 阻止默認刪除行為}}return true; // 允許默認刪除行為
})
技術要點
功能API說明
刪除監聽aboutToDelete()監聽刪除操作,可阻止默認行為
內容選中setSelection()選中指定范圍的內容
獲取內容getSpans()獲取指定位置的span信息

通過 RichEditor.aboutToDelete 事件監聽刪除操作,使用 RichEditorController.setSelection 實現@好友組件的整體選中和刪除。

5. 內容獲取與展示

功能概述

當用戶完成評論編輯后,需要獲取編輯區域的所有內容(文字、表情、@好友),并進行統一的數據處理和展示。

內容展示效果

數據類型映射

通過 RichEditorController.getSpans 獲取編輯區域內容,返回值包含 RichEditorTextSpanResult 和 RichEditorImageSpanResult 兩種類型。

不同內容類型與數據類型的對應關系:

textSpan可通過RichEditorTextSpanResult.value獲取文字內容。imageSpan可通過RichEditorImageSpanResult.valueResourceStr獲取圖片資源。但是builderSpan在RichEditorImageSpanResult中獲取不到任何相關的內容信息,所以在點擊好友頭像添加@好友內容時需要手動將這些builderSpan進行維護。

實際開發中編輯區域不同類型的內容往往需要一種統一的數據結構來表達,方便傳輸和存儲。該數據結構需要不僅能對編輯區域內容進行記錄,也需要有攜帶一些額外信息的能力,比如攜帶@好友相關的用戶信息。本文定義為RichEditorSpan。(實際開發中需要的屬性字段根據需求靈活調整)。

使用RichEditorSpan[]類型的數組builderSpans來維護@好友時的builderSpan,需要注意的是要保證每個builderSpan在數組中的順序要與實際內容中出現的順序一致。在添加builderSpan時,通過計算當前光標位置前面builderSpan的個數,來確定添加到builderSpans數組中的位置,并把需要攜帶的好友信息放入data屬性中。

發送評論時,將獲取到的內容用RichEditorSpan[]類型的數組richEditorSpans進行統一地表達。通過getSpans獲取所有內容,如果是textSpan,通過value屬性取出文字內容,設置RichEditorSpan.type為text,如果是imageSpan,通過valueResourceStr屬性獲取圖片資源,設置RichEditorSpan.type為image。如果是builderSpan,按順序從數組builderSpans中獲取,并將他們按順序添加到richEditorSpans中。

最終生成的richEditorSpans數據格式如下:

當需要展示評論內容時,只需要對richEditorSpans進行遍歷,根據type屬性,分別對文字、表情、@好友進行展示邏輯的處理。具體展示形式開發者根據實際需求確定。

  • 選擇圖片

    點擊圖片按鈕拉起系統相冊,選擇本地圖片進行上傳。該功能使用場景相對獨立,本文不詳細介紹。開發者需要進一步了解詳情,可參考以下sample。

    • 選擇并查看文檔和媒體文件
    • 文件管理
    • 發布圖片評論

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/84281.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/84281.shtml
英文地址,請注明出處:http://en.pswp.cn/web/84281.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Git 回退操作詳解:帶示例的“小白”指南

前言 在日常開發中,我們難免會遇到: 改錯代碼:推送之前才發現某些行根本就不該動提交錯誤:commit 信息打錯、提交到錯誤分支想回到之前版本:測試時發現之前版本是好的,需要回去查看 這就需要用到 Git 的…

redux以及react-redux

1.redux案例完整版 上一篇文章我們是沒有action文件,直接在countre組件與store以及reducer直接進行狀態的改變以及展示。 下面我們加上action文件,我們就不能直接通過dispatch傳,而是通過調用action里面的函數講我們傳入的參數變成action這種…

idea中配置svn及提交提示“未檢測到更改”提示

首先要安裝TortoiseSVN,選command line client tools; 在idea中,文件->設置->Subversion->如下圖 文件->設置->目錄映射->如下圖 初次導入到svn, 輸入服務器上的svn地址,等待成功即可;…

vue 實現dot-dropdown

<template><div class"app-container"><div class"mt30"></div><el-row :gutter"20"><!-- title --><!-- <div class"modt-box">導航管理</div> --><el-col :span"2&q…

使用 mysql2/promise 模塊返回以后,使用 await 返回數據總結

SELECT 返回結構 const [rows, fields] await db.query(SELECT * FROM folders);返回&#xff1a; rows: 是一個數組&#xff0c;包含所有查到的記錄。fields: 是字段的結構定義&#xff08;列信息&#xff09;&#xff0c;一般不用。 rows 是一個數組&#xff0c;包含所有…

Manus Metagloves pro高精度+無漂移+低延遲 ,重構VR/XR手部交互方式

manus metagloves pro是一款專為動畫制作、虛擬現實及游戲開發打造的高精度無線動作捕捉手套。采用先進的Quantum追蹤技術&#xff0c;實現毫米級動作捕捉&#xff0c;精準還原手指細節&#xff0c;顯著提升創作效率與交互真實感。 MANUS Metagloves Pro解鎖動捕 / 機器人 / XR…

Uniapp插件改造指南:如何讓vue-plugin支持HarmonyOS5原生能力?

一、分層架構設計 采用通用邏輯與平臺實現分離的三層結構&#xff1a; uni-plugin-harmony ├── common # 跨平臺通用層 │ ├── interfaces # 能力接口抽象&#xff08;如Scanner.ets&#xff09; │ └── utils # 工具類 ├── harmony …

P1040 [NOIP 2003 提高組] 加分二叉樹 題解

題目描述 設一個 n n n 個節點的二叉樹 tree \text{tree} tree 的中序遍歷為 ( 1 , 2 , 3 , … , n ) (1,2,3,\ldots,n) (1,2,3,…,n)&#xff0c;每個節點都有一個分數&#xff08;均為正整數&#xff09;。任一棵子樹 subtree \text{subtree} subtree&#xff08;包含 tr…

【Golang面試題】Data Race 問題怎么檢測?

Go Race Detector 深度指南&#xff1a;原理、用法與實戰技巧 一、什么是數據競爭&#xff1f; 在并發編程中&#xff0c;數據競爭發生在兩個或多個 goroutine 同時訪問同一內存位置&#xff0c;且至少有一個是寫操作時。這種競爭會導致不可預測的行為和極其難以調試的問題。…

257. 二叉樹的所有路徑(js)

257. 二叉樹的所有路徑——DFS 回溯&#xff08;js&#xff09; 題目描述解題思路完整代碼時間復雜度分析 題目描述 257. 二叉樹的所有路徑 解題思路 題意理解 給定一棵二叉樹&#xff0c;要求返回所有從根節點到葉子節點的路徑&#xff0c;路徑以字符串形式表示&#xff0c…

自動化文檔生成工具(親測可運行)

本文介紹了一個用Java編寫的自動化文檔生成工具&#xff0c;通過讀取開發清單文本自動生成格式規范的Word文檔。該工具的主要特點包括&#xff1a; 采用Apache POI庫處理Word文檔&#xff0c;支持多級標題和段落自動生成實現中文數字轉換功能&#xff0c;將編號轉換為"一、…

湖北理元理律師事務所債務優化模型:法律與生活的平衡之道

在債務重組領域&#xff0c;專業機構需同時解決兩個矛盾&#xff1a;法律合規性與債務人可持續生存能力。湖北理元理律師事務所通過“三維干預模型”&#xff0c;在武漢某餐飲連鎖企業債務危機中驗證了該方案的有效性。 一、法律底層設計&#xff1a;還款方案的合法性審查 以該…

Web3-代幣ERC20/ERC721以及合約安全溢出和下溢的研究

Web3-代幣ERC20/ERC721以及合約安全溢出和下溢的研究 以太坊上的代幣 如果你對以太坊的世界有一些了解&#xff0c;你很可能聽人們聊過代幣— ERC20代幣 一個 代幣 在以太坊基本上就是一個遵循一些共同規則的智能合約——即它實現了所有其他代幣合約共享的一組標準函數&…

論文筆記 <交通燈><多智能體>MetaLight:基于價值的元強化學習用于交通信號控制

今天看的論文是這篇MetaLight:基于價值的元強化學習用于交通信號控制 里面提到的創新點就是MetaLight框架&#xff1a;他目標是讓交通信號控制智能體&#xff08;Agent&#xff09;在新路口&#xff08;即使結構或流量模式不同&#xff09;上能??快速學習??&#xff08;Few…

華為OD-2024年E卷-尋找符合要求的最長子串[200分] -- python

問題描述&#xff1a; 給定一個字符串s&#xff0c;找出這樣一個子串: 1)該子串中的任意一個字符最多出現2次; 2)該子串不包含指定某個字符; 請你找出滿足該條件的最長子串的長度。 輸入描述 第一行為要求不包含的指定字符&#xff0c;為單個字符&#xff0c;取值范圍[0-9a-zA…

CppCon 2016 學習:What C++ Programmers Need to Know about Header <random>

隨機數生成的歷史背景 Middle-Square 方法&#xff08;中位平方法&#xff09;&#xff1a; 已知最早的隨機算法之一或由修道士 Brother Edvin 在 1245 年發明由 John von Neumann 在 1949 年重新發現缺點明顯&#xff0c;但執行速度快 Monte Carlo 方法&#xff1a; 起初是…

Origin:誤差棒點線圖繪制

1.首先將你的數據復制到表格 2.選中B(y)列數據&#xff0c;依次點擊圖示選項 3.選中圖中紅框數據&#xff0c;點擊繪制點線圖即可 4.結果展示

Spring 源碼學習 1:ApplicationContext

Spring 源碼學習 1&#xff1a;ApplicationContext Bean 定義和 Bean 實例 AnnotationConfigApplicationContext 首先&#xff0c;創建一個最簡單的 Spring Boot 應用。 在入口類中接收SpringApplication.run的返回值&#xff1a; SpringBootApplication public class Dem…

CppCon 2017 學習:Design Patterns for Low-Level Real-Time Rendering

這段內容講的是離散顯卡&#xff08;Discrete GPU&#xff09;中的內存管理模型&#xff0c;重點是CPU和GPU各自獨立管理自己的物理內存&#xff0c;以及它們如何通過虛擬內存和DMA引擎實現高效通信。以下是詳細的理解和梳理&#xff1a; 1. 基本概念 CPU 和 GPU 是兩個獨立的…

【單調隊列】-----【原理+模版】

單調隊列 一、什么是單調隊列&#xff1f; 單調隊列是一種在滑動窗口或區間查詢中維護候選元素單調性的數據結構&#xff0c;通常用于解決“滑動窗口最大值/最小值”等問題。 核心思想是&#xff1a;利用雙端隊列&#xff08;deque&#xff09;維護當前窗口內或候選范圍內元素…