【愚公系列】保姆級教程帶你實現HarmonyOS手語猜一猜元服務

🚀前言

最近HarmonyOS NEXT大火,這個純血鴻蒙吸引力了大家的關注。雖然現在還沒面向個人開發者開放,但我們可以基于最新的API9及開發工具來嘗試開發鴻蒙新的應用形態——元服務。來體驗下未來在HarmonyOS NEXT上實現的應用開發。

HarmonyOS是華為公司開發的操作系統,它的設計理念是面向未來的全場景智慧體驗,可在各種設備上運行,包括手機、平板電腦、智能手表、智能音箱等。HarmonyOS采用分布式技術,可以將不同設備之間的計算資源連接起來,實現設備間的協同工作,提高系統的性能和穩定性。此外,HarmonyOS還擁有高度自適應的界面、多屏協同等特性,使用戶能夠在不同設備上實現無縫的體驗。

本文主要是基于手語學習元服務的開發案例:主要的功能有

  • 元服務內部功能:
    • 1、提供專業手語翻譯老師示范視頻,包括基本手勢、字母表、常用短語等。用戶可以點擊觀看示范并模仿。
    • 2、提供類似答題模塊,幫助用戶鞏固所學的手語知識,用戶可以完成答題模塊測試自己的進步。
  • 元服務卡片:
    • 1、卡片界面展示每日一題,并可以在卡片上進行答題學習

項目實現效果如下:

元服務內部功能視頻:

元服務卡片功能視頻:

🚀一、HarmonyOS元服務簡介

🔎1.什么是元服務

元服務(原名為原子化服務)是HarmonyOS提供的一種面向未來的服務提供方式。它是一種新型應用程序形態,具有獨立入口、免安裝的特點,可以為用戶提供一個或多個便捷服務。

以線上購物為例,傳統購物應用需要先安裝應用,打開應用查找商品,加入購物車,然后完成支付。而通過元服務的方式,可以將購物過程拆分為多個服務,例如“商品瀏覽”、“購物車”、“支付”等,無需安裝應用,通過豐富的入口直達服務頁面。例如,將心儀的商品頁添加到桌面,可以實時掌握商品價格的變動。在秒殺時間點,可以直接進入購物車進行結算。

元服務基于HarmonyOS API開發,為用戶在合適的場景、合適的設備上提供便捷的使用體驗。相比傳統的需要安裝的應用形態,元服務更加輕量,同時提供更豐富的入口和更精準的分發。它為用戶提供了更靈活、更高效的服務方式,提升了用戶體驗和便利性。

🔎2.元服務的獨特價值

元服務的呈現形態之一是鴻蒙萬能卡片,它是元服務最主要的展示方式之一(其他形態包括語音、圖標等)。每一個萬能卡片都是一個在桌面上“永遠打開的”元服務/應用,以卡片的形式展示元服務/應用的重要信息,并通過輕量級的交互行為實現服務的直達。

元服務帶來了體驗上的變革,具體表現在以下幾個方面:

  1. 免安裝:元服務以更輕量化的方式將服務提供給用戶,無需進行繁瑣的應用安裝過程,節省了用戶的時間和存儲空間。
  2. 一鍵服務直達:元服務將用戶感興趣的內容前置、外顯,通過一鍵操作即可直接進入所需的服務頁面,提供了更快捷、便利的服務體驗。
  3. 跨端轉移:元服務支持多終端設備間的無縫流轉,用戶可以在不同的設備上無縫切換使用元服務,提供了更連貫、一致的服務體驗。
  4. 情景智能卡片推薦:元服務可以根據用戶的需求和偏好進行情景智能卡片推薦,用戶可以隨心定制自己的服務卡片,并根據個人喜好進行個性化設置,從而更好地滿足用戶的需求。

通過以上的變革,元服務為用戶帶來了更輕便、更直觀、更智能的服務體驗,提升了用戶的便利性和滿意度。

🔎3.元服務的應用場景

🦋3.1 負一屏

負一屏旨在提供更快速便捷的信息和服務,采用了宮格設計,將常用服務進行分類,涵蓋了本地生活、智慧出行、購物娛樂、金融理財等多個場景。用戶通過右滑進入發現頁,即可輕松地獲取所需的服務,無需下載繁瑣的App。此外,負一屏還具備實時狀態的新體驗,用戶使用服務后可以隨時查看進度,掌握關鍵節點信息。

🦋3.2 應用市場

打開華為應用市場,點擊“應用”頁簽,進入“元服務”專區發現并使用元服務。

🦋3.3 桌面

用戶可以將元服務的卡片添加到桌面,便可在桌面隨時隨地查看元服務的重要信息,點擊卡片即可直達所需服務。

🦋3.4 碰一碰/掃一掃

用戶首次“碰一碰”或者“掃一掃”識別設備上的NFC標簽,系統引導用戶連接設備,連接成功后,再次“碰一碰”或者“掃一掃”即可直接使用相應的元服務。

🚀二、開發環境搭建

🔎1.DevEco Studio

DevEco Studio是一款專門為鴻蒙(HarmonyOS)系統開發而設計的綜合性開發工具IDE,開發者可以利用該工具進行鴻蒙應用的設計、開發、調試和發布。DevEco Studio集成了代碼編輯器、模擬器、調試工具、圖形用戶界面設計器和應用管理工具等多個功能,方便開發者進行鴻蒙應用的開發與管理。

DevEco Studio支持多語言開發,包括Java、ArkTS、JavaScript等,同時還支持多種開發模式和框架。此外,它還支持多平臺開發,包括手機、平板、智能手表、電視等不同終端設備。

DevEco Studio下載地址:HUAWEI DevEco Studio和SDK下載和升級 | HarmonyOS開發者

安裝完成之后界面:

🔎2.配置環境變量

本文以window系統為例,具體操作步驟如下:

1、通過“設置 > 系統 > 系統信息 > 高級系統設置”進入“系統屬性”頁面的“高級”頁簽,點擊“環境變量”

2、在“系統變量”中添加 HDC_SERVER_PORT和OHOS_HDC_SERVER_PORT 兩個變量,變量值設置為未被占用的端口,例如7036和7037

3、在用戶或者系統的path變量中,添加HDC工具的路徑。
HDC工具路徑為:HarmonyOS SDK安裝目錄/hmscore/{版本號}/toolchains。例如:C:\Users\XXXXX\AppData\Local\Huawei\Sdk\hmscore\3.1.0\toolchains

環境變量配置完成,重啟DevEco Studio。

🔎3.診斷開發環境

1、打開項目,從歡迎頁進入:底部菜單選擇“Help > Diagnose Development Environment”


2、待自動檢查完成。如果有檢查未通過的項目,請根據檢查項的描述和修復建議進行處理

🔎4.下載SDK

1、打開項目,從歡迎頁進入:底部菜單選擇“Configure > Settings”

🚀三、創建元服務項目

🔎1.創建元服務項目的步驟

1、登錄AppGallery Connect, 點擊“我的應用”。

首次進入需要簽協議


2、在“HarmonyOS”頁簽,“類型”選擇“元服務”,可以查看創建的元服務。

🔎2.選擇模板和配置項目屬性

1、打開DevEco Studio,菜單選擇“File > New > Create Project”,創建一個新工程。

2、選擇“Atomic Service”,選擇“Empty Ability”模板,點擊“Next”。

3、配置工程基本信息。

  • Project name:設置“myProject”。
  • Bundle name:本樣例以“com.huawei.myproject”為例。
  • Save location:選擇工程存放路徑。
  • Compile SDK:支持API 4~9,本樣例選擇“API 9”。
  • Model:應用支持的模式,API Version 4~8只支持FA模式。
  • Enable Super Visual:是否使用低代碼開發模式,本樣例不打開此開關。
  • Language:開發語言。
  • Device type:該工程模板支持的設備類型。本樣例以手機設備為例。

點擊“Finish”,等待工程創建完成,即可進行代碼編寫。

🔎3.編寫代碼和調試運行

1、點擊右側的Previewer工具,預覽頁面效果。

2、新建details.ets頁面

details.ets頁面

@Entry
@Component
struct Details {build() {//Flex容器組件Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {//Text組件Text('我是跳轉頁面').fontSize(60).fontWeight(500)}//容器整體寬高.width('100%').height('100%')}
}

main_pages.json頁面

{"src": ["pages/Index","pages/details"]
}

3、添加跳轉按鈕實現頁面跳轉

index.ets頁面

import router from '@ohos.router'
@Entry
@Component
struct Index {@State message: string = '愚公搬代碼'build() {//Flex容器組件Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {//Text組件Text('愚公搬代碼').fontSize(60).fontWeight(500)//Button組件Button('跳轉下一頁').fontSize(40).fontWeight(500).width(280).height(60)//點擊Button實現頁面跳轉.onClick(() => {console.info("跳轉開始")router.pushUrl({url: 'pages/details' // 目標url}, (err) => {if (err) {console.error(`Invoke pushUrl failed, code is ${err.code}, message is ${err.message}`);return;}console.info('Invoke pushUrl succeeded.');});})}//容器整體寬高.width('100%').height('100%')}
}

🚀四、元服務代碼分析

🔎1.元服務代碼結構介紹

  • AppScope中存放應用全局所需要的資源文件。
  • entry是應用的主模塊,存放HarmonyOS應用的代碼、資源等。
  • oh_modules是工程的依賴包,存放工程依賴的源文件。
  • build-profile.json5是工程級配置信息,包括簽名、產品配置等。
  • hvigorfile.ts是工程級編譯構建任務腳本,hvigor是基于任務管理機制實現的一款全新的自動化構建工具,主要提供任務注冊編排,工程模型管理、配置管理等核心能力。
  • oh-package.json5是工程級依賴配置文件,用于記錄引入包的配置信息。

🦋1.1 AppScope

  • element文件夾主要存放公共的字符串、布局文件等資源。
  • media存放全局公共的多媒體資源文件。

🦋1.2 entry

  • entryability用于當前ability應用邏輯和生命周期管理。
  • entryformability用于當前卡片生命周期管理。
  • pages存放UI界面相關代碼文件,初始會生成一個Index頁面。
  • ohosTest是單元測試目錄。
  • build-profile.json5是模塊級配置信息,包括編譯構建配置項。
  • hvigorfile.ts文件是模塊級構建腳本。
  • oh-package.json5是模塊級依賴配置信息文件。
  • resources目錄下存放模塊公共的多媒體、字符串及布局文件等資源,分別存放在element、media文件夾中。

🔎2.開發選型

HarmonyOS 3.1及以上版本支持ArkTS、JS語言和Stage模型和FA模型兩種模型,其中Stage模型為從HarmonyOS 3.1開始新增的模型,將是長期演進的模型。

HarmonyOS中的Stage模型是指應用程序的窗口管理器和圖形引擎。Stage模型包含一個場景(Scene)和多個舞臺(Stage),每個舞臺表示一個窗口。在舞臺上,可以添加多個UI元素(如Button、Label、Image等),通過對UI元素進行布局、組合和交互,實現應用程序的功能。

在HarmonyOS中,通過Stage模型,可以實現窗口管理、多任務處理、圖形渲染和事件處理等功能。同時,Stage與HarmonyOS系統的分層架構緊密結合,可以自動適配不同屏幕、不同分辨率的設備,保證應用程序在各種設備上的兼容性和可用性。

一個應用包含一個或者多個Module,以下是Module與UIAbility組件關系示意圖:

編譯后的示意圖:

🔎3.元服務中常用的API和類

  1. OHOS::AAFwk::Ability: 這是Ability的基類,提供了啟動、停止和生命周期管理等能力。
  2. OHOS::AAFwk::Want: 跨應用程序組件之間傳遞的信息,可以指定Intent和Bundle等參數。
  3. OHOS::AppExecFwk::EventHandler: 用于在Ability生命周期內處理異步任務,支持延遲執行和定時執行。
  4. OHOS::EventFwk::EventRunner: 用于實現異步事件的執行和處理。
  5. OHOS::AGP::Window: 應用程序窗口,用于顯示UI界面。
  6. OHOS::AGP::View: UI界面中的基本控件,如Button、TextView等。
  7. OHOS::DataAbility::DataAbilityHelper: 數據能力的基礎類,用于管理數據的增刪改查操作。
  8. OHOS::DistributedSchedule::DistributedSchedulPolicy: 分布式調度策略,用于實現分布式系統的任務調度。
  9. OHOS::Media::MediaPlayer: 用于播放音頻和視頻文件。
  10. OHOS::Security::Permission: 權限管理類,用于管理應用程序對系統資源的訪問權限。

🚀五、案例展示:手語猜一猜

🔎1.案例背景

手語學習元服務的案例背景主要是為了幫助人們學習手語,提高對聾人的理解和尊重。聾人由于聽力障礙,無法通過聲音語言進行交流,而手語是聾人交流的主要方式。手語學習元服務通過數字化的方式提供了學習手語的機會,讓更多的人能夠了解手語,學習手語,以便更好地與聾人交流和理解聾人的需求。

隨著社會的不斷發展,聾人的教育和融入社會的問題日益重要。手語學習應用可以提供數字化的手語課程,讓更多的人能夠學習手語,提高對聾人的理解和尊重,促進聾人的教育和融入社會。

手語是一種非常有意義的語言,它不僅可以讓聾人與人進行有效的交流,還可以幫助聽力正常的人了解和尊重聾人的文化和生活習慣。手語學習應用也可以成為一個重要的手語文化傳播平臺,讓更多的人了解和學習手語,促進手語文化的傳播和發展。

🔎2.功能簡介

元服務:
1、提供專業手語翻譯老師示范視頻,包括基本手勢、字母表、常用短語等。用戶可以點擊觀看示范并模仿。
2、提供類似答題模塊,幫助用戶鞏固所學的手語知識,用戶可以完成答題模塊測試自己的進步。

元服務卡片:
1、卡片界面展示每日一題,并可以在卡片上進行答題學習

🔎3.案例實現流程

🦋3.1 內部應用功能

??3.1.1 首頁功能

首頁功能主要包含了4塊功能:每日挑戰、課程、測試、學習記錄

🌈3.1.1.1 每日挑戰

每日挑戰主要的交互有2塊功能:換一換和答題

換一換:主要實現題目和資源的切換(替換題目、替換視頻鏈接)

答題:主要是根據選項遍歷出Button按鈕,在根據按鈕點擊事件判斷點擊的按鈕type等于1則答題正確

源碼片段如下:

Flex({ justifyContent: FlexAlign.SpaceBetween }){Text('每日挑戰').fontSize(20).fontColor('#fff').width('50%')Column() {Flex({ justifyContent: FlexAlign.End  }) {Image(this.ic_new).width(20).height(20).margin({right:5})Text('換一批').fontSize(20).fontColor('#fff').onClick(()=>{this.anyArray=[{name:'吃',type:1},{name:'厲害',type:0}]this.videoSrc=$rawfile('quick.mp4')this.previewUri=$r('app.media.quick')})}.width('50%')}
}.padding(10).backgroundColor('#938cf4')Column(){Column(){Flex({justifyContent:FlexAlign.SpaceBetween}){Text('根據視頻所示,選擇正確的答案').fontSize(12).fontColor('#fff')Text('40%的人答錯').fontSize(12).fontColor('#fff')}.padding({top:10,left:10,right:10,bottom:10}).margin({top:0})Video({src: this.videoSrc,previewUri: this.previewUri,currentProgressRate: this.curRate,controller: this.controller}).width('100%').height(180).padding(5).borderRadius(1).margin({top:0,left:10,right:10,bottom:10,})Flex({justifyContent:FlexAlign.SpaceBetween}){ForEach(this.anyArray,(item)=>{Button(item.name,{ type: ButtonType.Normal,}).borderRadius(0).width('45%').backgroundColor('#ff986ec8').onClick(()=>{if(item.type==1){if (this.dialogController != undefined) {this.dialogController.open()this.textValue='答對了'}}else{if (this.dialogController != undefined) {this.dialogController.open()this.textValue='答錯了'}}})})}.margin({top:0,left:10,right:10,bottom:10,})}.backgroundColor('#ffa49fea').margin({top:0,left:10,right:10,bottom:10,}).borderRadius(10)}.backgroundColor('#938cf4')
🌈3.1.1.2 課程

這邊主要是點擊按鈕跳轉到課程頁面一個功能

源碼片段如下:

Column() {Flex({ alignItems: this.alignItems }) {Text('課程').width('50%').fontSize(20).fontWeight(FontWeight.Bold)}.size({width: '90%',}).padding({top:20,left:10,bottom:0})Flex({ justifyContent: FlexAlign.SpaceBetween }) {Text('初級課程,易上手').width('70%').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#c4c2cf')Button('學習').width('30%').backgroundColor('#fecc5b').margin({top:-25,}).onClick(()=>{router.push({ url: 'pages/list' })})}.size({width: '100%', }).padding({ left: 30 ,top:10,right:30,bottom:20},).border({radius:{bottomLeft: 15, bottomRight: 15}})
}.width('90%')
.backgroundColor('#fff')
.borderRadius(15)
.margin(20)
🌈3.1.1.3 測試

這邊主要是點擊按鈕跳轉到測試頁面一個功能

源碼片段如下:

Column() {Flex({ alignItems: this.alignItems }) {Text('課程').width('50%').fontSize(20).fontWeight(FontWeight.Bold)}.size({width: '90%',}).padding({top:20,left:10,bottom:0})Flex({ justifyContent: FlexAlign.SpaceBetween }) {Text('初級課程,易上手').width('70%').fontSize(16).fontWeight(FontWeight.Bold).fontColor('#c4c2cf')Button('學習').width('30%').backgroundColor('#fecc5b').margin({top:-25,}).onClick(()=>{router.push({ url: 'pages/list' })})}.size({width: '100%', }).padding({ left: 30 ,top:10,right:30,bottom:20},).border({radius:{bottomLeft: 15, bottomRight: 15}})
}.width('90%')
.backgroundColor('#fff')
.borderRadius(15)
.margin(20)
🌈3.1.1.4 學習記錄

這邊主要是基于組件的形式在界面展示,功能點主要有:時間數據、學習課程數

  • 時間數據:已當前時間自動更新
  • 學習課程數:來源于已學課程的本地存儲數據(存儲來源在課程學習界面)

源碼片段如下:

PersistentStorage.PersistProp('course', 0);let date = new Date()
let time = date.getFullYear() + "年" + (date.getMonth() + 1) + "月" + date.getDate() + "日"
console.log(time);
@Component
export default struct studyCollect {alignItems : number = 0// @State timeDate:string = date@StorageLink('course') course: number = 0@State dayTime:string=time;build() {Column() {Flex({ alignItems: this.alignItems }) {Text('學習記錄').width('50%').fontSize(20).fontWeight(FontWeight.Bold)Text(` ${this.dayTime}`).width('50%').height(30).textAlign(TextAlign.End)}.size({width: '90%', height: 50}).margin({top:10}).padding(10)Flex({ alignItems: this.alignItems }) {Text(`已學${this.course}課程`).width('50%').height(20).fontSize(16).fontWeight(FontWeight.Bold).fontColor('#fff')Text(`${this.course}分鐘`).width('50%').height(20).textAlign(TextAlign.End).fontColor('#fff')}.size({width: '100%', height: 50}).padding({ left: 40 ,top:15,right:40,},).border({radius:{bottomLeft: 15, bottomRight: 15}}).backgroundColor('#938cf4')}.width('90%').backgroundColor('#fff').borderRadius(15).margin({top:5})}
}
??3.1.2 課程功能

課程主頁面主要是課程信息展示和跳轉到具體詳情頁面

源碼片段如下:

import router from '@ohos.router';import { arrImage } from '../common/json'
@Entry
@Component
struct list {scroller: Scroller = new Scroller();@State arrImage: Object[]=arrImagebuild() {Scroll(this.scroller) {Column() {Column({ space: 5 }) {Text('初級課程').fontSize(20).fontColor('#fff').width('90%').padding(10).backgroundColor('')Flex({ wrap: FlexWrap.Wrap, justifyContent: FlexAlign.SpaceBetween }) {ForEach(this.arrImage, (item) => {Column() {Image(item.image).width('100%').height(120)Text(item.name).lineHeight(30)}.width('45%').height(150).backgroundColor(0xF5DEB3).margin(5).onClick(()=>{router.pushUrl({url:'pages/details',params:{text:item.name,image:item.image,video:item.video}})})})}.width('100%').padding(10).backgroundColor(0xAFEEEE)}.width('100%').margin({ top: 5 })}.width('100%').backgroundColor('#938cf4')}.backgroundColor(0xDCDCDC).scrollable(ScrollDirection.Vertical) // 滾動方向縱向.scrollBar(BarState.On) // 滾動條常駐顯示.scrollBarColor(Color.Gray) // 滾動條顏色.scrollBarWidth(5) // 滾動條寬度.edgeEffect(EdgeEffect.Spring) // 滾動到邊沿后回彈}
}
🌈3.1.2.1 課程詳情頁

功能點主要有:路由數據、客戶對課程的狀態信息

  • 路由數據:手語答案、手語視頻地址
  • 客戶對課程的狀態信息:點贊、收藏、轉發相關狀態變更

源碼片段如下:

import router from '@ohos.router'
import promptAction from '@ohos.promptAction'import { CommonTitleBar } from '../common/CommonTitleBar';@Entry
@Component
struct Index {@StorageLink('course') course: number = 0// @State good:Resource=$r('app.media.icon_good');@State goodStatus:boolean=true@State goodNumber:number=0@State startStatus:boolean=true@State startNumber:number=0@State shareStatus:boolean=true@State shareNumber:number=0@State text: string = router.getParams()['text']@State previewUri: Resource = router.getParams()['image']@State videoSrc: Resource = router.getParams()['video']@State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_Xcontroller: VideoController = new VideoController()alignItems : number = 0build() {Column(){// CommonTitleBar({attribute: {//   bg_color: '#ff2ad4b2',//   close_text: '返回',//   closeCallback: () => {////   },//   title_text: '標題',//   menuCallback: () => {////   }// }})Column(){Column(){Video({src: this.videoSrc,previewUri: this.previewUri,currentProgressRate: this.curRate,controller: this.controller}).width('100%').height(180).padding(10).borderRadius(10).onFinish(() => {this.course += 1;console.info('onFinish')})}Flex(){Text('當前示例:').fontSize(24)Text(`${this.text}`).fontSize(24)}.padding(10)Flex({}){Flex(){Image(this.goodStatus ? $r("app.media.icon_good"):$r("app.media.active_icon_good")).width(24).height(24)Text(`${this.goodNumber}`).height(25)}.width('20%').onClick(()=>{this.goodStatus=!this.goodStatus;this.goodStatus ? this.goodNumber--:this.goodNumber++;promptAction.showToast({message: this.goodStatus ? '取消點贊' :'點贊成功',duration: 2000,});})Flex(){Image(this.startStatus ? $r("app.media.icon_star"):$r("app.media.active_icon_star")).width(24).height(24)Text(`${this.startNumber}`).height(25)}.width('20%').onClick(()=>{this.startStatus=!this.startStatus;this.startStatus ? this.startNumber--:this.startNumber++;promptAction.showToast({message: this.startStatus ? '取消收藏' :'收藏成功',duration: 2000,});})Flex(){Image(this.shareStatus ? $r("app.media.icon_share"):$r("app.media.active_icon_share")).width(24).height(24)Text(`${this.shareNumber}`).height(25)}.width('20%').onClick(()=>{this.shareStatus=!this.shareStatus;this.shareStatus ? this.shareNumber--:this.shareNumber++;promptAction.showToast({message: this.shareStatus ? '取消轉發' :'轉發成功',duration: 2000,});})}.padding(10)}}//容器整體寬高.width('100%').height('100%').backgroundColor('#ff0f2ff')}
}
??3.1.3 測試功能

測試功能頁面主要功能是從json的題庫取出10題,如果答題正確會自動切換到下一題。

源碼片段如下:

import router from '@ohos.router'import promptAction from '@ohos.promptAction'
import { arrImage } from '../common/json'
@Entry
@Component
struct Index {@State onActive : number = 1@State arrImage: Object[]=arrImage@State videoSrc: Resource = $rawfile('hello.mp4')@State previewUri: Resource = $r("app.media.hello")@State curRate: PlaybackSpeed = PlaybackSpeed.Speed_Forward_1_00_Xcontroller: VideoController = new VideoController()alignItems : number = 0@State message: string = '手語猜猜看'@State studyName: string = '手語閱覽'@State collectName: string = '手語挑戰'@State testName: string = '測試'@State arr: string[] =['你好','出生','愛','晚飯','中午','明天']build() {Column(){Column(){Flex({alignItems:ItemAlign.Center,justifyContent:FlexAlign.Center}){// Text(`${this.arrImage[this.onActive]['name']}`)Text(`${this.onActive}`).fontSize(28)Text('/').fontSize(28)Text(`${this.arrImage.length}`).fontSize(28)}.margin(10)Column(){Video({src: this.arrImage[this.onActive-1]['video'],previewUri: this.arrImage[this.onActive-1]['image'],currentProgressRate: this.curRate,controller: this.controller}).width('100%').height(180).margin({top:0,bottom:0,})}Column({}){Text('在下列選項中選擇正確答案?').width('100%').padding(10).fontSize(20)}.backgroundColor('#fff')Flex({wrap: FlexWrap.Wrap }){ForEach(this.arrImage[this.onActive-1]['answer'],(item:string)=>{Button(item,{ type: ButtonType.Normal,}).margin(5).borderRadius(5).onClick(() => {console.log(item)if(this.onActive>=this.arrImage.length){promptAction.showToast({message: '闖關已結束',duration: 2000,});router.back({url:'pages/index'});return false;}if(item==this.arrImage[this.onActive-1]['name']){promptAction.showToast({message: '答對了,請繼續下一題',duration: 2000,});this.onActive=this.onActive+1;}else{promptAction.showToast({message: '答錯了',duration: 2000,});}})})}.padding(10)}}//容器整體寬高.width('100%').height('100%').backgroundColor('#ff0f2ff')}
}

🦋3.2 卡片功能

這邊和每日挑戰功能類似,主要多了些動畫效果,卡片主要的交互有2塊功能:換一換和答題

  • 換一換:主要實現題目和資源的切換(替換題目、替換視頻鏈接)
  • 答題:主要是根據選項遍歷出Button按鈕,在根據按鈕點擊事件判斷點擊的按鈕type等于1則答題正確

源碼片段如下:

@Entry
@Component
struct WidgetCard {@State onActive:number=0@State arrImage: Object[] = [{name:'你好',image:$r("app.media.hello"),content:'一手食指指向對方。一手握拳,向上伸出拇指。',video:$rawfile('hello.mp4'),anyArray:[{name:'你好',type:1},{name:'謝謝',type:0}]},{name:'謝謝',image:$r('app.media.thank'),content:'一手伸出拇指,彎曲兩下,表示向人感謝。',video:$rawfile('thank.mp4'),anyArray:[{name:'不好',type:0},{name:'謝謝',type:1}]},{name:'愛',image:$r('app.media.love'),content:'一手輕輕撫摩另一手拇指指背,表示一種“憐愛”的感情',video:$rawfile('love.mp4'),anyArray:[{name:'沒有',type:0},{name:'愛',type:1}]},{name:'喜歡',image:$r('app.media.live'),video:$rawfile('like.mp4'),content:'一手拇、食指微曲,指尖抵于頜下,頭微微點動一下。	',anyArray:[{name:'沒有',type:0},{name:'喜歡',type:1}]},{name:'不喜歡',image:$r('app.media.dislike'),video:$rawfile('dislike.mp4'),content:'一手伸直,左右擺動幾下。	一手拇、食指微曲,指尖抵于頜下,頭微微點動一下。	',anyArray:[{name:'好暈',type:0},{name:'不喜歡',type:1}]},{name:'飯',image:$r('app.media.eat'),video:$rawfile('eat.mp4'),content:'(一)一手拇、食指相對,中間留有米粒大小距離。(二)一手伸食、中指象征筷子,作吃飯動作。',anyArray:[{name:'可愛',type:0},{name:'飯',type:1}]},{name:'快',image:$r('app.media.quick'),video:$rawfile('quick.mp4'),content:'一手拇、食指相捏,很快地從一側向另一側作快速揮動,象征物體運動速度很快。',anyArray:[{name:'慢',type:0},{name:'快',type:1}]},{name:'慢',image:$r('app.media.slow'),video:$rawfile('show.mp4'),content:'一手掌心向下,慢慢地上下微動幾下,象征物體運動速度緩慢。',anyArray:[{name:'去',type:0},{name:'慢',type:1}]},{name:'沒關系',image:$r('app.media.matter'),video:$rawfile('matter.mp4'),content:'一手拇、食、中指捻動,連續幾次。	兩手拇、食指搭成圓圈,互相套環。	',anyArray:[{name:'人類',type:0},{name:'沒關系',type:1}]},{name:'厲害',image:$r('app.media.powerful'),video:$rawfile('powerful.mp4'),content:'一手打手指字母“L”的指式,并繞臉部轉一圈。同時面部作出嚴厲的表情。	',anyArray:[{name:'好帥',type:0},{name:'厲害',type:1}]},];/** The max lines.*/readonly MAX_LINES: number = 1;/** The action type.*/readonly ACTION_TYPE: string = 'router';/** The message.*/readonly MESSAGE: string = 'add detail';/** The ability name.*/readonly ABILITY_NAME: string = 'EntryAbility';/** The with percentage setting.*/readonly FULL_WIDTH_PERCENT: string = '100%';/** The height percentage setting.*/readonly FULL_HEIGHT_PERCENT: string = '100%';@State opacityAngle: number =  0.8@State mainFlag: boolean = false;@State flag: boolean = true;build() {Stack() {if(this.flag){Image(this.arrImage[this.onActive]['image']).width(this.FULL_WIDTH_PERCENT).height(this.FULL_HEIGHT_PERCENT).objectFit(ImageFit.Cover).opacity(this.opacityAngle).transition({ type: TransitionType.Insert, translate: { x: 0, y: 0 } }).transition({ type: TransitionType.Delete, opacity: 0, scale: { x: 0, y: 0 } })}else{Image(this.arrImage[this.onActive]['image']).width(this.FULL_WIDTH_PERCENT).height(this.FULL_HEIGHT_PERCENT).objectFit(ImageFit.Cover).opacity(this.opacityAngle).transition({ type: TransitionType.Insert, translate: { x: 0, y: 0 } }).transition({ type: TransitionType.Delete, opacity: 0, scale: { x: 0, y: 0 } })}Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Center }){Image($r("app.media.ic_new")).width(11).height(11).margin({left:10,top:3,right:5})Text("換一批").fontSize('8fp').width(40).fontColor('#fff').margin({top:3})}.backgroundColor('#fecc5b').width(50).height(15).borderRadius(10).onClick(()=>{animateTo({ duration: 1000 }, () => {this.flag = !this.flag;this.onActive=(this.onActive+1)%this.arrImage.length;})}).position({ x: 10, y: 10 })Column(){Flex({justifyContent:FlexAlign.SpaceBetween}){ForEach(this.arrImage[this.onActive]['anyArray'],(item)=>{Button(item.name,{ type: ButtonType.Normal,}).fontSize('8fp').borderRadius(10).height(20).width('45%').backgroundColor('#fecc5b').onClick(()=>{console.log('44')if(item.type==1){animateTo({ duration: 1000 }, () => {this.flag = !this.flag;this.onActive=(this.onActive+1)%this.arrImage.length;})}else{}})})}}.margin({top:110,left:10,right:10})Text(this.arrImage[this.onActive]['content']).fontSize('7fp').opacity($r('app.float.detail_immersive_opacity')).margin({ top: '70vp',left:'10vp',right:'10vp' }).textOverflow({ overflow: TextOverflow.Ellipsis }).fontColor('#000').fontWeight('900').maxLines(this.MAX_LINES)}.width(this.FULL_WIDTH_PERCENT).height(this.FULL_HEIGHT_PERCENT).onClick(() => {postCardAction(this, {"action": this.ACTION_TYPE,"abilityName": this.ABILITY_NAME,"params": {"message": this.MESSAGE}});})}
}

元服務項目源碼:https://download.csdn.net/download/aa2528877987/88484307

🚀總結

手語猜一猜元服務的實現借助了HarmonyOS的跨應用數據共享和功能交互特性,讓用戶可以通過手勢輸入手語,并進行識別和猜詞游戲。這種應用方式不僅提供了娛樂和互動的體驗,還促進了手語的學習和交流。通過使用該應用,我深刻體會到了HarmonyOS元服務的便利和靈活性。

開發使用HarmonyOS元服務可以帶來許多好處,包括跨設備互聯、數據共享和交互、靈活性和擴展性,以及性能優化。我鼓勵大家積極嘗試使用HarmonyOS元服務,開發出更好屬于自己的應用。

🚀附錄

  • 元服務介紹:元服務-元服務萬能卡片-元服務開發解決方案-華為開發者聯盟
  • ArkTS語言介紹: ArkTS 語言 - HarmonyOS應用開發官網
  • 端云一體化開發介紹:文檔中心
  • 低代碼開發介紹:文檔中心

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

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

相關文章

什么是高防IP?有什么優勢?怎么選擇高防IP?

在當今的互聯網環境中,分布式拒絕服務(DDoS)攻擊已經成為一種常見的安全威脅。這種攻擊通過向目標服務器發送大量的無效流量,使其無法處理正常的請求,從而達到迫使服務中斷的目的。作為一個用戶,你是否曾遇…

QGIS文章五——對遙感影像進行土地類型分類—監督分類(dzetsaka : classification tool)...

dzetsaka classification tool是QGIS的強大分類插件,目前主要提供了高斯混合模型分類器、Random Forest、KNN和SVM四種分類器模型,相比于SCP(Semi-Automatic Classification),他的一個特點就是功能專一,操作簡單。 從十一月開始一…

Linux基礎命令3

移動,剪切文件 普通文件的移動剪切 現在在這兒 上圖中,mv y.x ./tmp的意思,就是將當前路徑下的y.x文件進行剪切,然后放到路徑為當前路徑下的tmp目錄文件夾里面 操作完成后可以cd tmp,ls看到y.x文件已經在里面了 現在…

facebook引流軟件需要具備什么功能

facebook引流軟件需要具備什么功能 用戶信息批量修改:可批量修改已登錄用戶的頭像、密碼、個人說明等信息。小號批量刷贊、評論:可以批量用Facebook小號給帖子、主頁等刷贊或評論。直播帖刷人氣/評論/分享:可以直接刷直播帖子的人氣、評論&a…

京東內部員工,爆料工資與公積金收入!

精彩回顧:進了央企,拿了戶口,卻感覺被困住了。 每個企業都有它的一套規則,哪些人適合加薪,哪些人適合拿獎金,哪些人適合給股票期權等等。但是說實話,很多人都只能拿底薪,這些福利啥的…

數據挖掘 K近鄰

什么時候用K近鄰? 交叉驗證的時候。最常見的交叉驗證方法是K折交叉驗證,其中數據集被均勻分成K個子集,稱為折,然后執行K次訓練和測試,每次選擇不同的折作為測試集,其余的作為訓練集。最后,將K次…

JavaScript編程基礎 – 對象

JavaScript編程基礎 – 對象 JavaScript Programming Essentials – Object 本文簡要介紹JavaScript面向對象編程,如何實現其中的對象以及實例演示,希望對大家學習JavaScript有所幫助。 1. 面向對象編程特點 面向對象編程(Object-Oriented Programmi…

淺談JDK動態代理(上)

作者簡介:大家好,我是smart哥,前中興通訊、美團架構師,現某互聯網公司CTO 聯系qq:184480602,加我進群,大家一起學習,一起進步,一起對抗互聯網寒冬 到目前為止&#xff0c…

Splunk 編寫高效 查詢語句

1: 背景: splunk 的查詢語句的是否優化,對是否節省資源有很大的影響。下面說一下大概的方法: There are a set of basic principles that you can follow to optimize your searches. Retrieve only the required data Move as little data as possible Parallelize as mu…

力扣OJ題講解——循環隊列

今天我們一起來做一道關于隊列的OJ題目,這是力扣題目622題,點擊題目鏈接可以直接跳轉,https://leetcode.cn/problems/design-circular-queue/ 首先,我們看到要求,需要我們實現哪些功能? 我們需要設置隊列長…

2023亞太杯數學建模A題B題C題選題建議,思路分析,模型代碼

目錄 ABC題思路模型代碼:獲取見文末名片,第一時間更新 視頻連接講解如上 A題思路:采果機器人的圖像識別技術思路模型代碼 B題思路:玻璃溫室中的微氣候法規 C題思路:我國新能源電動汽車的發展趨勢 ABC題思路模型代…

經典雙指針算法試題(二)

📘北塵_:個人主頁 🌎個人專欄:《Linux操作系統》《經典算法試題 》《C》 《數據結構與算法》 ??走在路上,不忘來時的初心 文章目錄 一、有效三角形的個數1、題目講解2、講解算法原理3、代碼實現 二、查找總價格為目標值的兩個商…

Excel使用技巧匯總

1 單元格內換行 altenter

Hutool

一、簡介 Hutool是一個小而全的Java工具類庫,通過靜態方法封裝,降低相關API的學習成本,提高工作效率,使Java擁有函數式語言般的優雅 官方文檔: https://www.hutool.cn/docs/#/ 二、包含組件 一個Java基礎工具類,對文…

allegro畫封裝時使用坐標指令無效

使用坐標指令時顯示:“Pick is outside the extent of the drawing…pick again” 這是因為你放的引腳已經超出你這個繪制界面的定義尺寸,需要到Setup->Design pararmeters…里面去將圖幅改大一點,如下圖所示: 然后點擊Design…

消息中間件——RabbitMQ(三)理解RabbitMQ核心概念和AMQP協議!

前言 本章學習,我們可以了解到以下知識點: 互聯網大廠為什么選擇RabbitMQ?RabbiMQ的高性能之道是如何做到的?什么是AMQP高級協議?AMQP核心概念是什么?RabbitMQ整體架構模型是什么樣子的?Rabbi…

P8599 [藍橋杯 2013 省 B] 帶分數(dfs+全排列+斷點判斷)

思路&#xff1a;1.深度枚舉所有排列情況 2.設置為每個排列設置兩個斷點&#xff0c;分為三部分&#xff1a;a,b,c 3.轉換為乘法判斷條件&#xff0c;滿足加一 代碼如下&#xff1a;&#xff08;可用next_permutation全排列函數代替dfs&#xff09; #include<iostream>…

機器學習調參指南:提升模型性能的關鍵步驟

諸神緘默不語-個人CSDN博文目錄 文章目錄 1. 理解模型的參數和超參數2. 使用網格搜索進行超參數調優3. 隨機搜索4. 貝葉斯優化5. 使用交叉驗證避免過擬合6. 考慮正則化7. 調整學習率和其他優化器參數8. 實驗和記錄9. 模型的早停法10. 總結 在機器學習和深度學習的領域中&#x…

全面的日志監控管理工具

企業網絡由眾多日志源組成。集中監控這些日志源有助于防止數據威脅和網絡攻擊&#xff0c;綜合日志監控解決方案可以自動執行日志管理流程&#xff0c;通過關聯日志來識別惡意活動&#xff0c;并幫助滿足IT合規性要求。 不同類型的日志監控 EventLog Analyzer 綜合日志監控解…

智慧法院檔案數字化解決方案

智慧法院檔案數字化解決方案可以采用以下步驟&#xff1a; 1. 確定數字化目標&#xff1a;明確數字化的目標和范圍&#xff0c;比如將所有的案件相關文件、紙質檔案和材料進行數字化。 2. 確定數字化流程&#xff1a;制定數字化的流程和標準&#xff0c;比如采用哪些設備和軟件…