0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

基于eTS的HamronyOS应用开发

HarmonyOS开发者 来源:HarmonyOS开发者 作者:HarmonyOS开发者 2022-07-15 09:20 次阅读

随着HarmonyOS 3.0 Beta版的发布,API Version 8新增了大批JS/eTS API接口,相信很多开发者已经迫不及待想体验基于eTS的HamronyOS应用开发。本期Codelab,我们将基于API Version 8实现一个HarmonyOS课程类应用,帮助大家学习eTS的声明式UI描述、循环渲染、状态数据管理等机制,体验基于eTS的极简高效开发。

一、整体介绍

在课程类应用界面中,左侧为课程分类导航栏,右侧为各个类别的课程内容。当用户上下滑动右侧课程内容时,左侧导航栏会跳转至对应的课程分类。当用户点击左侧导航栏的课程分类时,会高亮显示点击的内容,且右侧课程内容会跳转至对应类别的课程列表。

那么如何基于eTS高效实现这样一个HarmonyOS课程类应用?下面我们将从声明式UI描述、循环渲染数据、状态数据管理三个维度来解析。

1. 声明式UI描述

界面布局是UI界面的骨架,决定了应用界面的交互和视觉风格。本示例中我们将通过eTS的一系列基础组件以声明式方式进行组合和扩展,并采用接近自然语义的编程语法直观地描述UI界面,包括参数构造配置、属性配置、事件配置以及子组件配置等。

相较于基于Java的命令式开发,eTS采用更接近自然语义的声明式编程语法,让开发者可以更直观地描述UI界面,有效地降低了开发者的上手成本,极大程度地提升了UI界面的构建效率,实现极简高效开发。

2. 循环渲染数据

数据模型是UI界面的肉体,描述了界面中数据的静态特征、动态行为和约束条件。本示例中我们将通过eTS直观地定义界面中各个模块的数据模型,包含名称、标识、图片链接等,并根据数据模型写入对应的数据。最后使用eTS提供的循环渲染机制(ForEach)将写入的数据循环渲染至对应的界面中。

相较于基于Java的命令式开发,eTS在渲染数据时UI的更新不需要开发者使用代码主动刷新,而是交给框架层自动处理,开发者不必关心框架如何实现UI绘制和渲染,实现界面数据的高效渲染。

3. 状态数据管理

联动效果是UI界面的灵魂,实现了界面中布局与数据的动态交互,本示例中我们将使用eTS提供的状态数据管理机制通过装饰组件拥有的状态属性,当装饰的变量更改时,组件会重新渲染更新UI界面数据,从而实现联动效果。

相较于基于Java的命令式开发,eTS通过功能不同的装饰器给开发者提供了清晰的页面更新渲染流程和管道。开发者要做的就是定义数据与UI的映射关系,后面只需要通过状态装饰器监听数据的状态,UI即可自动刷新,这极大地减轻了程序员对UI的维护工作。

以上就是实现课程类应用的核心原理,下面我们将为大家带来各部分的具体实现。

二、搭建界面布局

eTS提供了多种布局方式,不仅保留了经典的弹性布局能力,也提供了列表、宫格、栅格布局和适应多分辨率场景开发的原子布局能力。如图1所示,本示例中整体布局使用Row沿水平方向布局容器,并设置背景颜色为白色,Row内部嵌套Scroll及List容器分别作为应用界面的导航栏布局和课程内容布局,下面我们将为你一一道来。 7f92ac6e-03db-11ed-ba43-dac502259ad0.png 图1 整体布局

1. 导航栏布局

应用界面的导航栏使用可滚动的容器组件Scroll来实现,Scroll内嵌Text组件用于显示“课程分类”名称,如图2所示: 7fa7daf8-03db-11ed-ba43-dac502259ad0.png

图2 导航栏布局

Scroll容器必须内置一个子组件,我们使用了垂直方向的布局容器Column,并设置填充高度为height('100%')。“课程分类”名称使用Text组件实现,并设置文字颜色为fontColor(0x696969)、文字大小为fontSize(16)、文字对齐方式为textAlign(TextAlign.Center)居中显示、高度为height(60)、宽度为width('100%')。

相关代码如下:

Scroll() {  Column() {    ForEach(this.tabArray.map((item1, index1) => {      return { index: index1, data: item1 };    }), item => {      Text(item.data.superName)        .fontColor(0x696969)        .backgroundColor(this.index == item.index ? 0xffffff : null)        .fontSize(16)        .width('100%')        .height(60)        .textAlign(TextAlign.Center)        .onClick(() => {          if (this.index != item.index) {            this.index = item.index            this.scroller.scrollToIndex(item.data.position)          }        })    }, item => '' + item.data)  }.height('100%')}.width(100).height('100%').backgroundColor(0xdddddd).scrollBar(BarState.Off)

(左右滑动,查看更多)

2. 课程内容布局

应用的课程内容部分的布局使用List列表容器来实现,并使用ForEach循环渲染listArray(课程内容)数据,如图3所示,课程内容布局包含头部和课程信息两部分(头部和左边的导航栏对应),下面我们将分别介绍头部及课程信息的布局的实现。 7fb1f984-03db-11ed-ba43-dac502259ad0.png

图3 课程内容布局

(1) 头部布局

头部使用Text组件实现,并设置了文字颜色为fontColor(0x696969)、文字大小为fontSize(20)、高度为height(40)、宽度为width('100%')填充、内边距为padding({ left: 10 })、背景颜色为backgroundColor(0xefefef)。同时,头部的ListItem设置了sticky(Sticky.Normal)属性,使其滑动到顶部时可以呈现固定的效果。代码如下:

if (item.tag) {  ListItem() {    Text(item.courseName)      .fontColor(0x696969)      .fontSize(20)      .height(40)      .width('100%')      .padding({ left: 10 })      .backgroundColor(0xefefef)  }.sticky(Sticky.Normal)

(左右滑动,查看更多)

(2) 课程信息布局

课程信息部分使用Stack堆叠容器,高度设置为height(120),设置子组件在容器内的对齐方式为Alignment.TopStart。Stack组件内嵌Image、Text、Divider组件,用于呈现课程图片、课程标题、课程价格及分割线等信息。具体如下:

●课程的图片使用Image组件呈现,设置宽度为width(130),高度为height(100),图片的缩放类型为objectFit(ImageFit.Fill),使图片填充满组件,并设置左边、顶部边距均10,使其组件居中对齐。代码如下:

Image(item.imageUrl)  .objectFit(ImageFit.Cover)  .width(130)  .height(100)  .margin({ left: 10, top: 10 })
(左右滑动,查看更多)

●课程名称使用Text组件,设置文字颜色为fontColor(0x363636)、文字大小为fontSize(14),最大显示行数为maxLines(2)两行,文本超长时的显示方式为TextOverflow.Clip,意为进行裁剪显示。代码如下:

Text(item.courseName)  .fontColor(0x363636)  .fontSize(14)  .margin({ left: 150, top: 12 })  .maxLines(2)  .textOverflow({ overflow: TextOverflow.Clip })

(左右滑动,查看更多)

●课程的价格使用Text组件,设置文字颜色为fontColor(0xff6600)、文字大小为fontSize(24),并使用了绝对定位position({ x: 0, y: '100%' })先让组件显示在Stack容器最底部的外边界下,然后使用锚点定位markAnchor({ x: 0, y: '100%' })使组件以自身高度向上偏移,让组件显示在Stack容器最底部。代码如下:

Text(item.price == 0 ? '免费' : '¥' + item.price)  .fontColor(0xff6600)  .fontSize(24)  .position({ x: 0, y: '100%' })  .markAnchor({ x: 0, y: '100%' })  .margin({ bottom: 18, left: 150 })
(左右滑动,查看更多)

●分割线使用Divider组件实现,并设置了分割线颜色为color(0xefefef)、分割线宽度为strokeWidth(0.7)、左右边距margin({ left: 10, right: 10 })均为10,并使用绝对定位position({ x: 0, y: '100%' })和锚点定位markAnchor({ x: 0, y: '100%' })使分割线呈现在Stack容器最底部。代码如下:

Divider()  .margin({ left: 10, right: 10 })  .color(0xefefef)  .strokeWidth(0.7)  .position({ x: 0, y: '100%' })  .markAnchor({ x: 0, y: '100%' })

(左右滑动,查看更多)

至此,我们已经实现了界面布局,此时界面只是一个没有任何内容的骨架。接下来我们将为应用界面添加数据模型。

三、构建数据模型

本章节我们将为大家介绍本示例中数据模型的定义、数据的预置以及数据的加载。

1. 定义数据模型

本示例需定义两个数据模型,分别是应用界面中左侧导航栏的“课程分类”和右侧的“课程内容”。其中:

●导航栏“课程分类”定义了名称(superName)和位置(position)属性。数据模型定义如下:

export class TabItem {  position: number; // 点击该分类时课程内容滑动到的位置  superName: string; // 课程分类标题

  constructor(position: number, superName: string) {    this.position = position;    this.superName = superName;  }}
(左右滑动,查看更多)

●“课程内容”定义了课程的名称(courseName)、课程的图片地址(imageUrl)、课程的价格(price)、判断是否为此类别课程头部的变量(tag)、课程所对应课程类别的索引位置(index),数据模型定义如下:

export class CourseItem {  tag: boolean; // 是否此类别课程的头部  index: number; // 课程所对应课程类别的索引位置  courseName: string; // 课程名称  imageUrl: string; // 图片地址price:number;//价格  constructor(tag: boolean, index: number, courseName: string, imageUrl: string, price: number) {    this.tag = tag;    this.index = index;    this.courseName = courseName;    this.imageUrl = imageUrl;    this.price = price;  }}

(左右滑动,查看更多)

2. 预置数据

在entry/src/main/ets/MainAbility/Model.ets文件中,放入准备好的模拟数据,其中,superId是课程分类的唯一标识、id是课程内容的唯一标识。格式如下:

const LinkData: any[] = [  {     "superId": 1,     "superName": "热门课程",     "id": 1,     "courseName": "应用市场介绍",     "imageUrl": "/image/image1.jpg",     "price": 0   }, {    "superId": 1,    "superName": "热门课程",    "id": 2,    "courseName": "上架流程",    "imageUrl": "/image/image2.jpg",    "price": 100  },  ... ]
(左右滑动,查看更多)

3. 加载数据更新UI

本章节将介绍如何加载本地构造的模拟数据并呈现到界面。

(1) 加载数据

在index.ets文件中,通过getLinkData()获取预置数据。

aboutToAppear() {  // 延时数据加载  setTimeout(() => {    let linkDataItem = getLinkData();    this.tabArray = linkDataItem.tabArray;    this.listArray = linkDataItem.listArray;    this.requestSuccess = true;  }, 2000)}

(左右滑动,查看更多)

(2) 渲染

●导航栏使用ForEach循环渲染tabArray(课程分类)数据。这里的ForEach的第一个参数需要使用数组的map()方法遍历。代码如下:

let superId: number = 0model.forEach((item) => {  if (superId != item.superId) {    let tabItem = new TabItem(this.listArray.length, item.superName);    this.tabArray.push(tabItem)

    let courseItem = new CourseItem(true, this.tabArray.length - 1, item.superName, '', 0);    this.listArray.push(courseItem)  }})
(左右滑动,查看更多)

●课程内容使用ForEach循环渲染listArray(课程内容)数据。代码如下:

ForEach(this.listArray, item => {  if (item.tag) {    ListItem() {    ......    }.sticky(Sticky.Normal)  } else {    ListItem() {      Stack({ alignContent: Alignment.TopStart }) {      ......      }.height(120)    }  }}, item => '' + item)
(左右滑动,查看更多)

通过上文的介绍,我们已经实现了应用界面的布局以及界面数据的呈现,此时界面就像没有灵魂的躯壳。下面我们将为大家介绍应用中联动效果的实现。

四、实现界面联动

本示例中的联动效果包括导航栏高亮显示、滑动课程内容对应导航栏变化、点击导航栏课程分类跳转到对应课程内容,下面我们将一一道来。

7fc0f9f2-03db-11ed-ba43-dac502259ad0.gif

1. 导航栏高亮显示

实现导航栏高亮显示,主要通过@State装饰器监听导航栏课程分类的索引值的状态变化,当用户滑动课程内容或点击导航栏,对应课程分类的索引值发生变化,此时将调用build方法进行UI刷新,从而实现导航栏背景色的修改。相关代码如下:

@State index: number= 0; // 导航栏课程分类的索引Text(item.data.superName)  .backgroundColor(this.index == item.index ? 0xffffff : null)

2. 右边滑动,左边变化

滑动右边课程内容,对应左边导航栏变化,主要通过onScrollIndex()事件来判断当前课程内容所属的课程分类,当用户滑动课程内容时,对应课程内容的索引值发生变化,导航栏的课程分类的索引值也随之变化。相关代码如下:

private scroller: Scroller = new Scroller()List({ scroller: this.scroller }) {  ......  }.onScrollIndex((firstIndex: number) => {  if (this.index != this.listArray[firstIndex].index) {    this.index = this.listArray[firstIndex].index  }})

3. 左边点击,右边跳转

点击左边导航栏跳转到对应课程内容,主要通过onClick()事件监听用户点击,当用户点击导航栏,scrollToIndex()方法会根据点击的导航栏课程分类的索引值跳转到对应的课程内容界面。相关代码如下:

Text(item.data.superName)  .onClick(() => {    if (this.index != item.index) {      this.index = item.index      this.scroller.scrollToIndex(item.data.position)    }  })

以上就是本期全部内容,通过本期Codelab的学习,相信你已经掌握了eTS的声明式UI描述、循环渲染、状态数据管理等机制,赶快趁热打铁,开发更多有趣的应用吧!

原文标题:基于eTS高效开发HarmonyOS课程类应用

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据
    +关注

    关注

    8

    文章

    7035

    浏览量

    89045
  • API接口
    +关注

    关注

    1

    文章

    84

    浏览量

    10438
  • HarmonyOS
    +关注

    关注

    79

    文章

    1975

    浏览量

    30209

原文标题:基于eTS高效开发HarmonyOS课程类应用

文章出处:【微信号:HarmonyOS_Dev,微信公众号:HarmonyOS开发者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    罗德与施瓦茨和ETS-Lindgren发布新一代无线技术OTA测试解决方案

    罗德与施瓦茨(以下简称“R&S”)和 ETS-Lindgren 持续合作,为新一代无线技术提供全面的OTA 测试解决方案。ETS-Lindgren 将R&S CMX500一体化信令
    的头像 发表于 12-18 11:24 229次阅读

    鸿蒙开发组件:DataAbility的生命周期

    应用开发者可以根据业务场景实现data.js/data.ets中的生命周期相关接口。DataAbility生命周期接口说明见下表。
    的头像 发表于 06-20 09:39 446次阅读

    esp32c3在别的.c文件用微妙函数ets_delay_us(20)函数报错怎么解决?

    没添加文件是这个错../main/motor.c:41:21: error: implicit declaration of function \'ets_delay_us\' [-Werror
    发表于 06-20 07:46

    鸿蒙开发:创建PageAbility

    通过DevEco Studio开发平台创建PageAbility时,DevEco Studio会在app.js/app.ets中默认生成onCreate()和onDestroy()方法,其他方法需要开发者自行实现。
    的头像 发表于 06-18 09:36 257次阅读
    鸿蒙<b class='flag-5'>开发</b>:创建PageAbility

    HarmonyOS实战开发-如何实现音频低时延录制和播放,AudioVivid音乐播放的相关功能

    ||||---Ability.test.ets // 自动化测试用例 具体实现 音频录制和播放-源码参考:audioRecording.cpp低时延录制开发指导文档低时延播放开发指导文档低时延录制
    发表于 05-11 20:26

    HarmonyOS实战开发-如何通过BlendMode属性来实现挂件和图片的混合

    ||---BlendModeView.ets // 视图层-应用主页面 模块依赖 本实例依赖common模块来实现日志的打印、资源 的调用、依赖动态路由模块来实现页面的动态加载。 最后 如果大家觉得这篇内容对学习鸿蒙开发有帮助,我想
    发表于 05-07 14:45

    HarmonyOS开发实例:【分布式数据管理】

    eTS中分布式数据管理的使用,包括KVManager对象实例的创建和KVStore数据流转的使用。
    的头像 发表于 04-11 09:57 940次阅读
    HarmonyOS<b class='flag-5'>开发</b>实例:【分布式数据管理】

    鸿蒙OS应用开发:【DevEco Studio3.0 和 3.1版本差异】

    自动生成对应的代码和资源模板。同时,DevEco Studio还提供了多种编程语言供开发者进行HarmonyOS应用/服务开发,包括Java、JS、eTS和C/C++。
    的头像 发表于 03-26 17:21 1159次阅读
    鸿蒙OS应用<b class='flag-5'>开发</b>:【DevEco Studio3.0 和 3.1版本差异】

    鸿蒙ArkUI开发实战:eTS版【笑话app】

    制作一款笑话app,使用ArkUI。
    的头像 发表于 03-25 16:04 453次阅读
    鸿蒙ArkUI<b class='flag-5'>开发</b>实战:<b class='flag-5'>eTS</b>版【笑话app】

    是德科技与ETS Lindgren合作推出NB-NTN OTA测试解决方案

    近日,是德科技与ETS Lindgren共同发布了一款创新的OTA测试解决方案,该方案专为测试支持窄带非地面网络(NB-NTN)技术的设备而设计。这一创新性的解决方案标志着双方在通信测试领域的深入合作,共同为NB-NTN技术的推广和应用提供了有力支持。
    的头像 发表于 03-14 10:57 732次阅读

    鸿蒙开发学习:【ets_frontend组件】

    ets_frontend组件采用命令行交互方式,支持将JavaScript代码转换为方舟字节码文件,使其能够在方舟运行时上运行。支持Windows/Linux/MacOS平台。方舟前端工具在linux平台上可通过全量编译或指定编译前端工具链获取。
    的头像 发表于 03-10 19:58 343次阅读
    鸿蒙<b class='flag-5'>开发</b>学习:【<b class='flag-5'>ets</b>_frontend组件】

    鸿蒙实战开发:【WLAN使用】

    eTS中WLAN的基本使用,包括禁用和启用WLAN、WLAN扫描和获取扫描结果、WLAN状态监听、WiFi连接状态监听、获取IP信息、获取国家码、判断设备是否支持WLAN相关特性。
    的头像 发表于 03-07 15:36 600次阅读
    鸿蒙实战<b class='flag-5'>开发</b>:【WLAN使用】

    鸿蒙实战项目开发:【短信服务】

    ; 需授予短信发送权限且插入SIM卡才可成功发送短信,有预置短信内容,每次退出应用数据会清空,未添加存储功能,发送短信为默认卡发送。 工程目录 entry/src/main/ets
    发表于 03-03 21:29

    鸿蒙开发【应用开发基础知识】

    通过OpenHarmony提供的Stage模型和ArkUI的eTS声明式开发规范,结合简单的Demo,分享学习OpenHarmony/docs/application-dev
    的头像 发表于 01-29 18:46 1371次阅读
    鸿蒙<b class='flag-5'>开发</b>【应用<b class='flag-5'>开发</b>基础知识】

    arkcompiler_runtime_core/static_core/runtime和arkcompiler_ets_runtime有什么关联

    arkcompiler_runtime_core/static_core/runtime有内存分配和垃圾回收,arkcompiler_ets_runtime也有独立的内存管理和垃圾回收。 这两个库之间是什么关系和作用
    发表于 01-10 21:39