用鸿蒙开发AI应用(六)UI篇

开发
文章由鸿蒙社区产出,想要了解更多内容请前往:51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com/#zz

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com/#zz

前言
 上一篇,我们在鸿蒙上写了一个HDF驱动并操作了一下LED硬件,这一篇我们来尝试一下构建一个有简单界面的App,体验一下鸿蒙的前端开发流程。

环境准备

1. 安装DevEco Studio

解压相应的压缩包(文末附下载链接),这里以win10为例,双击`deveco-studio-2.0.12.201.exe`

 
指定安装目录
 
设置可选快捷方式和环境变量
 
一路下一步即可。
 

同意用户协议后,就能正常启动了。

 
2. 更新sdk
 
在菜单 `Setting->HarmonyOS SDK->SDK Platforms`中,选择`Js`和`Java`,安装新版的`SDK`。
 

同样在`SDK Tools`中,选中新版的`Previewer`。

 

点击Apply更新

 

新建项目

点击菜单`File->New Project...`,选择智慧屏`Smart Vision`,创建一个空模板应用。

填入项目名称`MyUiAPP`,点击完成就能创建一个工程了。
 
遇到 `gradle`下载太慢或版本差异的,可以直接在以下网址用工具下载。
 
  1. https://services.gradle.org/distributions/ 

目录结构

我们先分析一下目录结构,做`Android`开发的会倍感亲切。

1. APP

`HarmonyOS`的应用软件包以`APP Pack(Application Package)`形式发布,它是由一个或多个`HAP(HarmonyOS Ability Package)`以及描述每个`HAP`属性的`pack.info`组成。`HAP`是`Ability`的部署包,`HarmonyOS`应用代码围绕`Ability`组件展开。

一个`HAP`是由代码、资源、第三方库及应用配置文件组成的模块包,可分为`entry`和`feature`两种模块类型。

- **entry**:应用的主模块。一个APP中,对于同一设备类型必须有且只有一个`entry`类型的`HAP`,可独立安装运行。

- **feature**:应用的动态特性模块。一个`APP`可以包含一个或多个`feature`类型的`HAP`,也可以不含。只有包含`Ability`的`HAP`才能够独立运行。

 

2. Ability

Ability是应用所具备的能力的抽象,一个应用可以包含一个或多个`Ability`。`Ability`分为两种类型:`FA(Feature Ability)`和`PA(Particle Ability)`。`FA/PA`是应用的基本组成单元,能够实现特定的业务功能。`FA`有`UI`界面,而`PA`无`UI`界面。

3. 资源文件

应用的资源文件(字符串、图片、音频等)统一存放于`resources`目录下,便于开发者使用和维护。`resources`目录包括两大类目录,一类为`base`目录与限定词目录,另一类为`rawfile`目录。

4. 配置文件

配置文件` (config.json) `是应用的`Ability`信息,用于声明应用的`Ability`,以及应用所需权限等信息。

- 应用的全局配置信息,包含应用的包名、生产厂商、版本号等基本信息。

- 应用在具体设备上的配置信息,包含应用的备份恢复、网络安全等能力。

- `HAP`包的配置信息,包含每个`Ability`必须定义的基本属性(如包名、类名、类型以及`Ability`提供的能力),以及应用访问系统或其他应用受保护部分所需的权限等。

5. JS UI 框架

`JS UI`框架是一种跨设备的高性能`UI`开发框架,支持声明式编程和跨设备多态`UI`。

- 声明式编程

`JS UI`框架采用类`HTML`和`CSS`声明式编程语言作为页面布局和页面样式的开发语言,页面业务逻辑则支持`ECMAScript`规范的`JavaScript`语言。`JS UI`框架提供

的声明式编程,可以让开发者避免编写`UI`状态切换的代码,视图配置信息更加直观。

- 跨设备

开发框架架构上支持`UI`跨设备显示能力,运行时自动映射到不同设备类型,开发者无感知,降低开发者多设备适配成本。

- 高性能

开发框架包含了许多核心的控件,如列表、图片和各类容器组件等,针对声明式语法进行了渲染流程的优化。

`JS UI`框架包括应用层`(Application)`、前端框架层`(Framework)`、引擎层`(Engine)`和平台适配层`(Porting Layer)`。

# 空气质量监测 UI

## 1. 创建首页面

空气质量监测App包含两个界面`(Page)`,工程创建完成后会生成一个名为`index`的`Page`,可以作为首页。

## 2. 创建详情页

在`pages`目录按右键,弹出的菜单中选择`New->JS Page`。

输入页面名称`detail`,
 

详情页创建完成后应用工程目录如下图所示,每个`Page`包括三个文件:布局文件`hml`、样式文件`css`、业务逻辑代码`js`。

## 3. 开发首页

应用首页主要展示城市的空气质量概况。首页总共有两屏(可以根据需求设置多屏),每屏显示一个城市的空气质量信息:主要包括AQI指数、城市名称、污染物指数、更新时间和信息来源等数据。

### 3.1 创建根节点

修改`entry/src/main/js/default/pages/index/index.hml`,加入根节点`div`:

  1. <div class="container"> 
  2. </div> 

### 3.2 创建样式

修改`entry/src/main/js/default/pages/index/index.css`

  1. container {     
  2.     flex-direction: column; 
  3.     height: 480px; 
  4.     width: 960px; 
 3.3 添加标题栏

标题栏包括一个退出按钮和一个标题,两个控件是横向排列

  1. <div class="container">     
  2.     <div class="header" onclick="exitApp">         
  3.         <image class="back" src="common/ic_back.png"></image>         
  4.         <text class="title">             
  5.             空气质量         
  6.          </text>     
  7.     </div> 
  8. </div> 

注意,这里要先导入common/ic_back.png图标资源。

3.4 添加标题栏样式

修改entry/src/main/js/default/pages/detail/detail.css,添加以下代码,设置组件的高度、边距、颜色等属性。

  1. .header {     
  2.     width: 960px; 
  3.     height: 72px; 
  4. .back {     
  5.     width: 36px; 
  6.     height: 36px; 
  7.     margin-left: 39px; 
  8.     margin-top: 23px; 
  9. .title {     
  10.     width: 296px; 
  11.     height: 40px; 
  12.     margin-top: 20px; 
  13.     margin-left: 21px; 
  14.     color: #e6e6e6; 

### 3.5 添加退出事件

`onclick="exitApp"` 设置了`div`组件的`click`事件,当在标题栏上触发点击事件时,就会执行函数`exitApp`,该函数位于`index.js`文件中,代码如下:

  1. exitApp() {   
  2.     console.log('start exit');   
  3.     app.terminate();   
  4.     console.log('end exit'); 

`app.terminate()`函数实现了程序退出功能;在使用该函数前,需要引入`app`模块,在`index.js`文件的最上方写如下代码:

  1. import app from '@system.app' 

在 Previewer 窗口中,可以预览界面效果

 

### 3.6 滑动组件

实现城市空气质量信息的多屏左右滑动,需要使用`“swiper”`组件。

在根节点中添加一个子节点`swiper`, 修改`index.hml`

  1. <swiper class="swiper" index="{{swiperPage}}" duration="500" onchange="swiperChange"> 
  2.  
  3. </swiper> 
 添加样式,修改`index.css`
 
  1. .swiper { 
  2.     height: 385px; 
  3.     width: 960px; 
 绑定`swiperPage`变量,`swiperChange`事件,修改`index.js`
 
  1. //引入router模块,用户页面跳转 
  2. import router from'@system.router' 
  3. import app from '@system.app' 
  4.   
  5. export default { 
  6.     //定义参数 
  7.     data: { 
  8.       //默认是第一页 
  9.       swiperPage: 0  
  10.     }, 
  11.     onInit () { 
  12.     }, 
  13.     exitApp(){   
  14.         console.log('start exit');   
  15.         app.terminate();   
  16.         console.log('end exit'); 
  17.     }, 
  18.     //swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中 
  19.     swiperChange (e) { 
  20.         this.swiperPage = e.index; 
  21.     } 

在`swiper`中添加两个子组件`stack`(绝对布局),每个`stack`组件内分别添加`text、image、progress`等组件来显示对应的信息。

  1. <div class="container"> 
  2.     <div class="header" onclick="exitApp"> 
  3.         <image class="back" src="common/ic_back.png"></image> 
  4.         <text class="title"> 
  5.             空气质量 
  6.         </text> 
  7.     </div> 
  8.     <swiper class="swiper" index="{{swiperPage}}" duration="500" onchange="swiperChange"> 
  9.         <!--第一屏--> 
  10.         <stack class="swiper"> 
  11.             <!--空气质量--> 
  12.             <text class="airquality" style="color:{{textColor1}};">{{airData[0].airQuality}}</text> 
  13.             <!--城市名称--> 
  14.             <text class="location-text">{{airData[0].location}}</text> 
  15.             <!--进度条--> 
  16.             <progress 
  17.                 class="circleProgress" 
  18.                 style="color:{{textColor1}};background-Color:{{bgColor1}};" 
  19.                 type="arc" 
  20.                 onclick="openDetail" 
  21.                 percent="{{percent1}}"> 
  22.             </progress> 
  23.             <!--云朵图片--> 
  24.             <image class="image" src="{{src1}}"></image> 
  25.             <!--AQI数值--> 
  26.             <text class="pm25-value">{{ airData[0].detailData }}</text> 
  27.             <text class="pm25-name">AQI</text> 
  28.             <!--空气指标详细信息--> 
  29.             <div class="detail"> 
  30.                 <div class="text-wrapper"> 
  31.                     <text class="gas-name"> 
  32.                         CO 
  33.                     </text> 
  34.                     <text class="gas-value"> 
  35.                         100 
  36.                     </text> 
  37.                 </div> 
  38.                 <div class="text-wrapper"> 
  39.                     <text class="gas-name"> 
  40.                         NO2 
  41.                     </text> 
  42.                     <text class="gas-value"> 
  43.                         90 
  44.                     </text> 
  45.                 </div> 
  46.                 <div class="text-wrapper"> 
  47.                     <text class="gas-name"> 
  48.                         PM10 
  49.                     </text> 
  50.                     <text class="gas-value"> 
  51.                         120 
  52.                     </text> 
  53.                 </div> 
  54.                 <div class="text-wrapper"> 
  55.                     <text class="gas-name"> 
  56.                         PM2.5 
  57.                     </text> 
  58.                     <text class="gas-value"> 
  59.                         40 
  60.                     </text> 
  61.                 </div> 
  62.                 <div class="text-wrapper"> 
  63.                     <text class="gas-name"> 
  64.                         SO2 
  65.                     </text> 
  66.                     <text class="gas-value"> 
  67.                         150 
  68.                     </text> 
  69.                 </div> 
  70.                 <input class="btn" type="button" onclick="openDetail" value="历史记录"></input> 
  71.             </div> 
  72.             <!--更新时间和网站等信息--> 
  73.             <div class="footer"> 
  74.                 <text class="update-time"> 
  75.                     更新时间: 10:38 
  76.                 </text> 
  77.                 <text class="info-source"> 
  78.                     信息来源: tianqi.com 
  79.                 </text> 
  80.             </div> 
  81.         </stack> 
  82.  
  83.         <!--第二屏--> 
  84.         <stack class="swiper"> 
  85.             <text class="airquality" style="color: {{textColor2}};">{{airData[1].airQuality}}</text> 
  86.             <text class="location-text">{{airData[1].location}}</text> 
  87.             <progress class="circle-progress" style="color: {{textColor2}};background-Color: {{bgColor2}};" type="arc" 
  88.                     percent="{{percent2}}"></progress> 
  89.             <image class="image" src="{{src2}}"></image> 
  90.             <text class="aqi-value">{{airData[1].detailData}}</text> 
  91.             <text class="aqi"> 
  92.                 AQI 
  93.             </text> 
  94.             <div class="detail"> 
  95.                 <div class="text-wrapper"> 
  96.                     <text class="gas-name"> 
  97.                         CO 
  98.                     </text> 
  99.                     <text class="gas-value"> 
  100.                         10 
  101.                     </text> 
  102.                 </div> 
  103.                 <div class="text-wrapper"> 
  104.                     <text class="gas-name"> 
  105.                         NO2 
  106.                     </text> 
  107.                     <text class="gas-value"> 
  108.                         50 
  109.                     </text> 
  110.                 </div> 
  111.                 <div class="text-wrapper"> 
  112.                     <text class="gas-name"> 
  113.                         PM10 
  114.                     </text> 
  115.                     <text class="gas-value"> 
  116.                         60 
  117.                     </text> 
  118.                 </div> 
  119.                 <div class="text-wrapper"> 
  120.                     <text class="gas-name"> 
  121.                         PM2.5 
  122.                     </text> 
  123.                     <text class="gas-value"> 
  124.                         40 
  125.                     </text> 
  126.                 </div> 
  127.                 <div class="text-wrapper"> 
  128.                     <text class="gas-name"> 
  129.                         SO2 
  130.                     </text> 
  131.                     <text class="gas-value"> 
  132.                         150 
  133.                     </text> 
  134.                 </div> 
  135.                 <input class="btn" type="button" onclick="openDetail" value="历史记录"></input> 
  136.             </div> 
  137.             <div class="footer"> 
  138.                 <text class="update-time"> 
  139.                     更新时间: 10:38 
  140.                 </text> 
  141.                 <text class="info-source"> 
  142.                     信息来源: tianqi.com 
  143.                 </text> 
  144.             </div> 
  145.         </stack> 
  146.     </swiper> 
  147. </div> 

### 3.7 页面位置指示器

添加页面位置指示器:由于当前`swiper`不支持设置`indicator`,需要开发者自己来实现该效果。在根节点中添加一个子组件`div`,并设置相应样式;然后在该`div`中添

加两个子组件`div`,设置两个`div`的`border-radius`,并在`swiper`滑动事件中动态改变对应`div`的背景色来实现该效果。

修改`index.hml`,在`swiper`组件后加入以下代码:

  1. <div class="images">     
  2.     <div class="circle-div" style="background-color: {{iconcheckedColor}};"></div>     
  3.     <div class="circle-div" style="background-color: {{iconUncheckedColor}};margin-left: 36px;"></div> 
  4. </div> 

### 3.8 新增文字样式

修改 `index.css`

  1. aqi-value { 
  2.     text-align: center; 
  3.     font-size: 65px; 
  4.     color: #f0ffff; 
  5.     width: 156px; 
  6.     height: 92px; 
  7.     top: 134px; 
  8.     left: 210px; 
  9. .aqi { 
  10.     text-align: center; 
  11.     color: #a2c4a2; 
  12.     width: 156px; 
  13.     height: 45px; 
  14.     top: 90px; 
  15.     left: 210px; 
  16. .airquality { 
  17.     top: 222px; 
  18.     text-align: center; 
  19.     width: 156px; 
  20.     height: 45px; 
  21.     left: 210px; 
  22. .image { 
  23.     top: 285px; 
  24.     left: 274px; 
  25.     width: 32px; 
  26.     height: 32px; 
  27. .location-text { 
  28.     text-align: center; 
  29.     color: #ffffff; 
  30.     width: 250px; 
  31.     height: 52px; 
  32.     font-size: 40px; 
  33.     left: 380px; 
  34.     top: 16px; 
  35. .container { 
  36.     flex-direction: column; 
  37.     height: 480px; 
  38.     width: 960px; 
  39. .circle-progress { 
  40.     center-x: 128px; 
  41.     center-y: 128px; 
  42.     radius: 128px; 
  43.     startAngle: 198; 
  44.     totalAngle: 320; 
  45.     strokeWidth: 24px; 
  46.     width: 256px; 
  47.     height: 256px; 
  48.     left: 160px; 
  49.     top: 58px; 
  50. .detail { 
  51.     width: 256px; 
  52.     height: 265px; 
  53.     left: 544px; 
  54.     top: 58px; 
  55.     flex-direction: column; 
  56. .text-wrapper { 
  57.     width: 256px; 
  58.     height: 35px; 
  59.     margin-top: 6px; 
  60. .gas-name { 
  61.     width: 128px; 
  62.     height: 35px; 
  63.     text-align: left; 
  64. .gas-value { 
  65.     width: 128px; 
  66.     height: 35px; 
  67.     text-align: right; 
  68. .btn { 
  69.     width: 180px; 
  70.     height: 50px; 
  71.     margin-top: 6px; 
  72.     margin-left: 38px; 
  73.     background-color: #1a1a1a; 
  74.     color: #1085CE; 
  75. .footer { 
  76.     top: 326px; 
  77.     width: 960px; 
  78.     height: 28px; 
  79. .header { 
  80.     width: 960px; 
  81.     height: 72px; 
  82. .back { 
  83.     width: 36px; 
  84.     height: 36px; 
  85.     margin-left: 39px; 
  86.     margin-top: 23px; 
  87. .title { 
  88.     width: 296px; 
  89.     height: 40px; 
  90.     margin-top: 20px; 
  91.     margin-left: 21px; 
  92.     color: #e6e6e6; 
  93. .swiper { 
  94.     height: 385px; 
  95.     width: 960px; 
  96. .images { 
  97.     width: 60px; 
  98.     height: 15px; 
  99.     margin-left: 450px; 
  100. .update-time { 
  101.     width: 480px; 
  102.     height: 28px; 
  103.     font-size: 20px; 
  104.     color: #A9A9A9; 
  105.     text-align: right; 
  106. .info-source { 
  107.     width: 450px; 
  108.     height: 28px; 
  109.     font-size: 20px; 
  110.     color: #A9A9A9; 
  111.     text-align: left; 
  112.     margin-left: 24px; 
  113. .circle-div { 
  114.     width: 12px; 
  115.     height: 12px; 
  116.     border-radius: 6px; 
 ### 3.9 实现页面逻辑

修改`index.js`,绑定页面数据`data`。初始化时,根据不同的数值显示不同的字体和图片`onInit`。实现页面跳转`openDetail`,将当前页面索引传递给`detail`页面。滑动触发后`swiperChange`改变指示位置。

  1. //引入router模块,用户页面跳转 
  2. import router from'@system.router' 
  3. import app from '@system.app' 
  4.  
  5. export default { 
  6. //定义参数 
  7.     data: { 
  8.         //页面绑定数据 
  9.         textColor1: "#00ff00", 
  10.         textColor2: "#00ff00", 
  11.         bgColor1: "#669966", 
  12.         bgColor2: "#669966", 
  13.         //默认是第一页 
  14.         swiperPage: 0, 
  15.         percent1: 10, 
  16.         percent2: 90, 
  17.         iconUncheckedColor: '#262626', 
  18.         iconcheckedColor: '#ffffff', 
  19.         iconcheckedBR: '6px', 
  20.         src1: "common/cloud_green.png", 
  21.         src2: "common/cloud_green.png", 
  22.         airData: [ 
  23.           { 
  24.             location: "HangZhou", 
  25.             airQuality: "Good", 
  26.             detailData: 10 
  27.           }, 
  28.           { 
  29.             location: "ShangHai", 
  30.             airQuality: "Unhealth", 
  31.             detailData: 90 
  32.           } 
  33.         ] 
  34.     }, 
  35.     onInit () { 
  36.         //根据数值的不同,设置不同的字体、背景颜色和图片 
  37.         if(this.airData[0].detailData > 100){ 
  38.             this.src1 = 'common/cloud_red.png'; 
  39.             this.textColor1 = '#ff0000'; 
  40.             this.bgColor1 = '#9d7462'; 
  41.         } else if(50 < this.airData[0].detailData && this.airData[0].detailData <= 100){ 
  42.             this.src1 = 'common/cloud_yellow.png'; 
  43.             this.textColor1 = '#ecf19a'; 
  44.             this.bgColor1 = '#9d9d62'; 
  45.         } 
  46.         if(this.airData[1].detailData > 100){ 
  47.             this.src2 = 'common/cloud_red.png'; 
  48.             this.textColor2 = '#ff0000'; 
  49.             this.bgColor2 = '#9d7462'; 
  50.         } else if(50 < this.airData[1].detailData && this.airData[1].detailData <= 100){ 
  51.             this.src2 = 'common/cloud_yellow.png'; 
  52.             this.textColor2 = '#ecf19a'; 
  53.             this.bgColor2 =  '#9d9d62'; 
  54.         } 
  55.         if(this.selectedCityIndex){ 
  56.             this.swiperPage = this.selectedCityIndex; 
  57.             if(this.swiperPage == 0){ 
  58.                 this.iconcheckedColor = '#ffffff'; 
  59.                 this.iconUncheckedColor = '#262626'; 
  60.             }else{ 
  61.                 this.iconcheckedColor = '#262626'; 
  62.                 this.iconUncheckedColor = '#ffffff'; 
  63.             } 
  64.         } 
  65.     }, 
  66.     //跳转到详情页面 
  67.     openDetail () { 
  68.         router.replace({ 
  69.             uri: 'pages/detail/detail', 
  70.             params: {selectedCityIndex:this.swiperPage} 
  71.         }); 
  72.     }, 
  73.     //退出应用 
  74.     exitApp(){ 
  75.         console.log('start exit'); 
  76.         app.terminate(); 
  77.         console.log('end exit'); 
  78.     }, 
  79.     //swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中 
  80.     swiperChange (e) { 
  81.         this.swiperPage = e.index; 
  82.         if(e.index == 0){ 
  83.             this.iconcheckedColor = '#ffffff'; 
  84.             this.iconUncheckedColor = '#262626'; 
  85.         }else{ 
  86.             this.iconcheckedColor = '#262626'; 
  87.             this.iconUncheckedColor = '#ffffff'; 
  88.         } 
  89.     } 
 预览效果如下:
 

## 4. 开发详情页

详情页以图表的形式展示一周内空气质量指标值。本页面由两部分组成:标题栏和图表栏;在图表栏,考虑显示效果,我们使用多个`div`替代`chart`组件来实现图表功能。

### 4.1 添加标题栏

修改 `entry/src/main/js/default/pages/detail/detail.hml`

  1. <div class="container"> 
  2.     <div class="header" onclick="backMain"> 
  3.         <image class="back" src="common/ic_back.png"></image> 
  4.         <text class="title"> 
  5.             历史记录 
  6.         </text> 
  7.     </div> 
  8.     <list class="chart-list"> 
  9.     </list> 
  10. </div> 

### 4.2 添加图表栏

添加城市位置到`list-item-title`,图表到`list-item-chart`

  1. <list class="chart-list"> 
  2.     <list-item class="list-item-title"> 
  3.         <text class="location">{{location}}</text> 
  4.     </list-item> 
  5.     <list-item class="list-item-chart"> 
  6.     </list-item> 
  7. </list> 
 4.3 添加图表
  1. <div class="chart-wrapper" style="margin-left: 128px;"> 
  2.     <text class="gas-name">CO</text> 
  3.     <div class="chart"> 
  4.         <div class="chart-item" style="height: 78px;background-color: #00ff00;"></div> 
  5.         <div class="chart-item" style="height: 52px;background-color: #00ff00;"></div> 
  6.         <div class="chart-item" style="height: 155px;background-color: #ff0000;"></div> 
  7.         <div class="chart-item" style="height: 134px;background-color: #ff0000;"></div> 
  8.         <div class="chart-item" style="height: 98px;background-color: #FF7500;"></div> 
  9.         <div class="chart-item" style="height: 88px;background-color: #FF7500;"></div> 
  10.         <div class="chart-item" style="height: 144px;background-color: #ff0000;"></div> 
  11.     </div> 
  12.     <div class="white-line"></div> 
  13.     <div class="week"></div> 
  14. </div> 
 4.4 添加样式
  1. .location { 
  2.     text-align: center; 
  3.     color: #ffffff; 
  4.     width: 960px; 
  5.     height: 52px; 
  6.     font-size: 40px; 
  7. .container { 
  8.     height: 480px; 
  9.     width: 960px; 
  10.     flex-direction: column; 
  11.  
  12. .header { 
  13.     width: 960px; 
  14.     height: 72px; 
  15.  
  16. .back { 
  17.     width: 36px; 
  18.     height: 36px; 
  19.     margin-left: 39px; 
  20.     margin-top: 23px; 
  21.  
  22. .title { 
  23.     width: 296px; 
  24.     height: 40px; 
  25.     margin-top: 20px; 
  26.     margin-left: 21px; 
  27.     color: #e6e6e6; 
  28.  
  29. .chart-list { 
  30.     width: 960px; 
  31.     height: 408px; 
  32.  
  33. .list-item-title { 
  34.     width: 960px; 
  35.     height: 52px; 
  36.  
  37. .list-item-chart { 
  38.     width: 960px; 
  39.     height: 280px; 
  40.  
  41. .chart-wrapper { 
  42.     width: 308px; 
  43.     height: 256px; 
  44.     flex-direction: column; 
  45.  
  46. .gas-name { 
  47.     width: 308px; 
  48.     height: 35px; 
  49.     text-align: left; 
  50.  
  51. .chart { 
  52.     width: 308px; 
  53.     height: 155px; 
  54.     margin-top: 10px; 
  55.     justify-content: flex-start; 
  56.     align-items: flex-end; 
  57.  
  58. .chart-item { 
  59.     width: 24px; 
  60.     margin-left: 18px; 
  61.     border-radius: 3px; 
  62.  
  63. .white-line { 
  64.     width: 308px; 
  65.     height: 2px; 
  66.     background-color: #ffffff; 
  67.     margin-top: 22px; 
  68.  
  69. .week { 
  70.     width: 308px; 
  71.     height: 17px; 
  72.     margin-top: 6px; 
  73.     border-color: #ffffff; 
  74.     border-radius: 2px; 
  75.     margin-top: 6px; 
  76.  
  77. .day { 
  78.     width: 26px; 
  79.     height: 17px; 
  80.     font-size: 10px; 
  81.     margin-left: 16px; 
  82.     text-align: center; 
 ### 4.5 实现页面跳转

其中`onclick="backMain"`为返回主页事件,根据传递的页面索引,显示不同的位置数据,`detail.js`中的代码实现如下:

  1. import router from '@system.router' 
  2.  
  3. export default { 
  4.     data: { 
  5.         location: '' 
  6.     }, 
  7.     onInit() { 
  8.         if (this.selectedCityIndex === 0) { 
  9.             this.location = '杭州'; 
  10.         } else { 
  11.             this.location = '上海'; 
  12.         } 
  13.     }, 
  14.     backMain() { 
  15.         router.replace({ 
  16.             uri: 'pages/index/index', 
  17.             params: { 
  18.                 selectedCityIndex: this.selectedCityIndex 
  19.             } 
  20.         }); 
  21.     } 
 

5. 模拟器调试

菜单Tools->HVD Manager,可以打开云端的模拟器

 
注册华为开发者账号,授权登录后
 
 
就能看到模拟器列表了,相比`beta`版只有`Phone`、`TV`和`Wearable`三种,增加了不少的设备。
 
 

可惜还没有可用于`smartVision`设备的模拟器,现阶段我们还只能烧录到设备中调试,总体上"富鸿蒙"的进度比较快,期待一波更新。

## 6. 编译打包

若开发手机端的`App`,则需要申请证书,对应用程序进行签名。这样才能发布到应用市场,才被允许安装到真机上运行。

`IPCamera`应用**暂时不支持签名模式**,所以需要将应用发布为未签名的应用安装包。

菜单`Build->Buildo APP(s)/Hap(s)->Build Release Hap(s)`,生成`Hap`文件。

输出文件为 `build/outputs/hap/release/smartVision/entry-release-smartVision-unsigned.hap`,改名为`MyUiApp.hap`便于安装。

## 7. 通过sdcard安装

### 7.1 复制安装包和工具

将IDE编译的未签名应用安装包和安装工具(`Z:\openharmony\out\my_hi3516dv300\dev_tools`)放在`sdcard`中,将`sdcard`插入开发板卡槽。

### 7.2 禁用签名校验

应用安装默认要校验签名,需要执行以下命令,关闭签名校验。

  1. ./sdcard/dev_tools/bin/bm set -s disable 
 

7.3 安装应用

  1. ./sdcard/dev_tools/bin/bm install -p /sdcard/MyUiApp.hap  
 

## 8. 通过NFS安装

每次插拔`sdcard`还是蛮不方便的,这里我们安装一个`NFS`服务器,让鸿蒙系统能直接访问`Win10`的目录,后续安装调试就会方便很多。

### 8.1 安装NFS服务器

我们先安装一个`haneWIN NFS服务器`, 双击文末网盘里的`nfs1169.exe`,一路下一步即可。

 

8.2 配置目录参数

编辑输出表文件,定义传输目录

 
  1. # exports example 
  2.  
  3. # C:\ftp -range 192.168.1.1 192.168.1.10 
  4. # c:\public -public -readonly 
  5. # c:\tools -readonly 192.168.1.4 
  6.  
  7. D:\PycharmProjects\aiLearn\Harmony\tftp -public -name:nfs 
 ### 8.3 重启服务

右键管理员权限,重启所有服务,让配置生效。

 

### 8.4 设置防火墙

防火墙设置`111、1058、2049`这些端口的`TCP`和`UDP`,入站规则放行。

  

### 8.5 鸿蒙上挂载目录

主电脑的`ip`地址为`192.168.1.57`,`NFS`服务的别名为`nfs`,对应的目录为`D:\PycharmProjects\aiLearn\Harmony\tftp`

  1. mkdir nfs 
  2. mount 192.168.1.57:/nfs /nfs nfs 
  挂载到鸿蒙的刚新建的 `/nfs`目录下,我们可以复制安装包和安装工具
 
 

8.6 安装应用

  1. cd nfs 
  2. ./dev_tools/bin/bm set -s disable 
  3. ./dev_tools/bin/bm install -p MyUiApp.hap 

前面做了这么多的铺垫,后续开发只要复制`hap`安装包,直接一条命令安装即可,非常方便。

 

# 运行程序

安装完成后,点击桌面上的`MyUiApp`就能看见界面效果了。

`Js UI框架`对开发者还是比较友好的,有小程序或快应用的开发经验,上手应该都比较顺滑。

不过`HarmonyOS Device`的支持库精简的非常严重,例如网络访问的`@system.request`和`@system.fetch`都不可用,这些功能在“富鸿蒙”的设备上开发就会比较方便。

# 资料下载

 

# 下一篇预告

> 本期主要介绍了一下JS框架下的界面开发,

> 下一篇我们将尝试熟悉更多的设备能力,

> 并打通从框架用户态到驱动内核态之间的联系,

> 敬请期待...

 
©著作权归作者和HarmonyOS技术社区共同所有,如需转载,请注明出处,否则将追究法律责任

想了解更多内容,请访问:

51CTO和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com/#zz

 

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2021-01-14 12:06:22

鸿蒙HarmonyOSAI应用

2021-01-15 09:50:06

鸿蒙HarmonyOSAI应用

2021-01-15 11:36:16

鸿蒙HarmonyOSAI应用

2021-01-19 12:46:45

鸿蒙HarmonyOSHelloworld

2024-06-07 13:11:44

2011-04-14 10:05:16

BlackBerry

2011-04-14 10:03:32

UI组件BlackBerry

2021-01-21 13:27:37

鸿蒙HarmonyOS应用开发

2021-10-18 10:14:26

鸿蒙HarmonyOS应用

2021-02-06 10:40:45

鸿蒙HarmonyOS应用开发

2020-11-09 11:56:49

HarmonyOS

2021-01-05 10:35:04

鸿蒙HarmonyOS应用开发

2021-11-24 16:02:57

鸿蒙HarmonyOS应用

2022-09-09 14:42:17

应用开发ETS

2024-11-11 16:22:15

2019-05-05 11:02:07

vscodevue前端

2009-12-09 10:48:50

ibmdwLotus

2024-11-15 11:30:58

2012-02-13 13:45:04

MonoTouch.NETiOS应用

2020-09-28 15:13:04

鸿蒙
点赞
收藏

51CTO技术栈公众号