1# 时钟应用开发指导<a name="ZH-CN_TOPIC_0000001115417926"></a> 2 3- [概述](#section11522349121115) 4- [开发准备](#section6592121861218) 5- [开发步骤](#section19901741111312) 6- [签名打包](#section10601181101516) 7- [真机运行](#section092721731511) 8- [常见问题](#section1122413460153) 9 - [hdc\_std连接不到设备](#section1922725151614) 10 - [hdc\_std运行不了](#section15657547131615) 11 12 13## 概述<a name="section11522349121115"></a> 14 15本文将介绍如何快速搭建基于OpenHarmony标准系统(Hi3516DV300开发板)的应用开发环境,并基于一个时钟APP示例逐步展示应用的创建、开发、调试和安装等流程。示例代码可以通过[本链接](https://gitee.com/openharmony/app_samples/tree/master/common/Clock)获取。 16 17时钟App是一款显示实时时间的应用,显示效果如下图所示: 18 19**图 1** 时钟应用显示效果图<a name="fig176772511186"></a> 20 21 22## 开发准备<a name="section6592121861218"></a> 23 24首先需要下载和配置DevEco Studio,具体操作请参考[DevEco Studio 使用指南](../../application-dev/quick-start/deveco-studio-user-guide-for-openharmony.md)。 25 26## 开发步骤<a name="section19901741111312"></a> 27 28应用的功能是通过表盘和数字显示实时时间。 29 30从[显示效果图](#fig176772511186)分析可知,页面由两个部分组成: 31 32- 表盘栏:主要展示一个动态的钟表,且钟表指针能准确转动。 33- 数字时间栏:主要以数字形式显示当前时间。 34 35综上,我们可搭建一个纵向两行排列的弹性页面布局来实现界面的功能。具体开发步骤如下: 36 371. 在hml文件中添加一个根节点div,注意每个hml文件中有且只能有一个根节点,代码如下: 38 39 ``` 40 <div class="container"> 41 </div> 42 ``` 43 44 class="container"表示组件使用的样式,container是index.css文件中的一个样式类,代码如下: 45 46 ``` 47 .container { 48 flex-direction: column; 49 justify-content: center; 50 align-items: center; 51 width: 100%; 52 height: 100%; 53 } 54 ``` 55 56 在这个样式类中,我们分别设置了根组件div的高度和宽度(注意在应用的开发过程中,除部分组件(text)外必须显式指定组件的高度和宽度,否则可能无法显示)、并将flex-direction属性设置为column,该属性表示div的子组件是垂直方向从上到下排列;这样就可以实现本节开头所说的纵向两行排列的弹性页面布局。 57 582. 实现时钟转动,需要使用“stack”组件。“stack”组件的功能是堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。 59 60 在根组件下添加一个stack容器,代码片段如下: 61 62 ``` 63 <div class="container"> 64 <stack class="stack"> 65 <image src="/common/clock_bg.png" class="clock-bg"></image> <!--设置表盘图片--> 66 <image src="/common/hour_hand.png" class="clock-hand" 67 style="transform : rotate({{ hour * 30 + minute / 2 }}deg);"></image> <!--设置时钟图片,(hour * 30)一小时旋转30度,(minute / 2)时钟每分钟旋转的角度--> 68 <image src="/common/minute_hand.png" class="clock-hand" 69 style="transform : rotate({{ minute * 6 + second / 10 }}deg);"></image> <!--设置分钟图片,(minute * 6)一分钟旋转6度,(second / 10)分钟每秒钟旋转的角度--> 70 <image src="/common/second_hand.png" class="clock-hand" 71 style="transform : rotate({{ second * 6 }}deg);"></image> <!--设置秒钟图片,(second * 6)一秒旋转6度--> 72 </stack> 73 </div> 74 ``` 75 76 style="transform : rotate\(\{\{ second \* 6 \}\}deg\) 这类代码用来设置组件的旋转事件。其中transform是设置动画平移/旋转/缩放的属性,rotate是旋转动画属性,支持设置x轴和y轴两个维度的选中参数。 77 78 在css文件中设置"stack"组件样式的高度、宽度、位置等属性,代码如下: 79 80 ``` 81 .stack { 82 flex-direction: column; 83 justify-content: center; 84 align-items: center; 85 width: 100%; 86 height: 50%; 87 } 88 ``` 89 90 在css文件中设置"clock-bg"组件样式的高度、宽度等属性,代码如下: 91 92 ``` 93 .clock-bg { 94 width: 80%; 95 height: 80%; 96 object-fit: scale-down; 97 } 98 ``` 99 100 在css文件中设置"clock-hand"组件为时针、分针和秒针的高度、宽度等属性,代码如下: 101 102 ``` 103 .clock-hand { 104 width: 25%; 105 height: 65%; 106 object-fit: contain; 107 } 108 ``` 109 110 index.js中会有一个定时器实时刷新时分秒变量,从而触发时间界面自动更新。对应的js代码如下: 111 112 ``` 113 export default { 114 timer: undefined, 115 //定义参数 116 data: { 117 hour: 0, //定义小时 118 minute: 0, //定义分钟 119 second: 0 //定义秒 120 }, 121 onInit () { 122 this.updateTime(); 123 this.timer = setInterval(this.updateTime, 1000)//设置1s的定时器 124 }, 125 updateTime: function () { 126 var nowTime = new Date() 127 this.hour = nowTime.getHours() 128 this.minute = nowTime.getMinutes() 129 this.second = nowTime.getSeconds() 130 if (this.hour < 10) { 131 this.hour = '0' + this.hour 132 } 133 if (this.minute < 10) { 134 this.minute = '0' + this.minute 135 } 136 if (this.second < 10) { 137 this.second = '0' + this.second 138 } 139 }, 140 } 141 ``` 142 1433. 显示数字时间,在钟表下面以数字形式显示当前时间。在根布局内末尾加上text组件,页面结构如下: 144 145 ``` 146 <text class="digit-clock"> {{ hour }}:{{ minute }}:{{ second }}</text> 147 ``` 148 149 class="digit-clock"设置了组件的高度和宽度以及字体大小,其代码如下: 150 151 ``` 152 .digit-clock { 153 font-size: 58px; 154 width: 100%; 155 margin-top: 0px; 156 text-align: center; 157 } 158 ``` 159 1604. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: 161 - **index.hml文件** 162 163 ``` 164 <div class="container"> 165 <stack class="stack"> 166 <image src="/common/clock_bg.png" class="clock-bg"></image> 167 <image src="/common/hour_hand.png" class="clock-hand" 168 style="transform : rotate({{ hour * 30 + minute / 2 }}deg);"></image> 169 <image src="/common/minute_hand.png" class="clock-hand" 170 style="transform : rotate({{ minute * 6 + second / 10 }}deg);"></image> 171 <image src="/common/second_hand.png" class="clock-hand" 172 style="transform : rotate({{ second * 6 }}deg);"></image> 173 </stack> 174 <text class="digit-clock">{{ hour }}:{{ minute }}:{{ second }}</text> 175 </div> 176 ``` 177 178 - **index.css文件** 179 180 ``` 181 .container { 182 flex-direction: column; 183 justify-content: center; 184 align-items: center; 185 width: 100%; 186 height: 100%; 187 } 188 189 .stack { 190 flex-direction: column; 191 justify-content: center; 192 align-items: center; 193 width: 100%; 194 height: 50%; 195 } 196 197 .digit-clock { 198 font-size: 58px; 199 width: 100%; 200 margin-top: 0px; 201 text-align: center; 202 } 203 204 .clock-bg { 205 width: 80%; 206 height: 80%; 207 object-fit: scale-down; 208 } 209 210 .clock-hand { 211 width: 25%; 212 height: 65%; 213 object-fit: contain; 214 } 215 ``` 216 217 - **index.js:** 218 219 js文件主要用于实现App应用的逻辑交互。在本页面js文件中,需要实现如下功能:定时获取系统时间。 220 221 ``` 222 export default { 223 timer: undefined, 224 data: { 225 hour: 0, 226 minute: 0, 227 second: 0 228 }, 229 onInit() { 230 this.updateTime() 231 this.timer = setInterval(this.updateTime, 1000) 232 }, 233 updateTime: function () { 234 var nowTime = new Date() 235 this.hour = nowTime.getHours() 236 this.minute = nowTime.getMinutes() 237 this.second = nowTime.getSeconds() 238 if (this.hour < 10) { 239 this.hour = '0' + this.hour 240 } 241 if (this.minute < 10) { 242 this.minute = '0' + this.minute 243 } 244 if (this.second < 10) { 245 this.second = '0' + this.second 246 } 247 }, 248 onDestroy() { 249 clearInterval(this.timer); 250 } 251 } 252 ``` 253 254 255 256## 签名打包<a name="section10601181101516"></a> 257 258代码编写完成后,在真机设备上运行应用,需要先对应用进行签名,然后再进行打包,具体操作请参考[签名打包指导](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ohos-debugging-and-running-0000001263040487#section17660437768)。 259 260## 真机运行<a name="section092721731511"></a> 261 262应用签名打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),然后将OpenHarmony系统烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[标准系统Hi3516快速入门](../quick-start/quickstart-standard-overview.md)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载应用。 263 2641. 从开发者工具代码仓路径中获取hdc客户端。 265 266 ``` 267 developtools/hdc_standard/prebuilt/windows/hdc_std.exe 268 ``` 269 270 修改名称为hdc.exe,并将工具路径加入系统环境path变量中。 271 2722. 启动cmd命令窗口,执行以下命令,推送hap应用包到设备目录下并安装。 273 274 ``` 275 hdc install clock.hap 276 ``` 277 2783. 启动应用。执行以下命令,其中ohos.samples.clock为应用包名,MainAbility为应用启动的Ability。 279 280 ``` 281 hdc shell aa start -d 123 -a ohos.samples.clock.MainAbility -b ohos.samples.clock 282 ``` 283 2844. 卸载应用(可选)。执行以下命令,其中ohos.samples.clock为应用包名。 285 286 ``` 287 hdc shell bm uninstall -n ohos.samples.clock 288 ``` 289 290 291## 常见问题<a name="section1122413460153"></a> 292 293### hdc\_std连接不到设备<a name="section1922725151614"></a> 294 295- **现象描述** 296 297 执行 "hdc\_std list targets"命令后结果为:\[Empty\] 298 299- **可能原因和解决方法** 300 1. 设备没有被识别: 301 302 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 303 304 2. hdc\_std工作异常: 305 306 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 307 308 3. hdc\_std与设备不匹配: 309 310 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 311 312 313 314### hdc\_std运行不了<a name="section15657547131615"></a> 315 316- **现象描述** 317 318 点击hdc\_std.exe文件无法运行。 319 320- **可能原因和解决方法** 321 322 hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 323 324 325