保姆级教程带你实现HarmonyOS手语猜一猜元服务(三)

由于文章篇幅较长,共分为了三篇发布

保姆级教程带你实现HarmonyOS手语猜一猜元服务(一)
保姆级教程带你实现HarmonyOS手语猜一猜元服务(二)
保姆级教程带你实现HarmonyOS手语猜一猜元服务(三)

🚀四、元服务代码分析

🔎1.元服务代码结构介绍

image.png

  • 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[]=arrImage

  build() {
    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_X
  controller: VideoController = new VideoController()
  alignItems : number = 0
  build() {
    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_X
  controller: 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元服务,开发出更好属于自己的应用。

为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05

《鸿蒙开发学习手册》:

如何快速入门:https://qr21.cn/FV7h05

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

开发基础知识:https://qr21.cn/FV7h05

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

基于ArkTS 开发:https://qr21.cn/FV7h05

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

鸿蒙开发面试真题(含参考答案):https://qr18.cn/F781PH

鸿蒙开发面试大盘集篇(共计319页):https://qr18.cn/F781PH

1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值