1# UIAbility内和UIAbility间页面的跳转 2## 场景介绍 3UIAbility组件是系统调度的基本单元,为应用提供绘制界面的窗口。一个应用可以包含一个或多个UIAbility组件。例如,在支付应用中,可以将入口功能和收付款功能分别配置为独立的UIAbility。 4 5对于开发者而言,可以根据具体场景选择单个还是多个UIAbility,划分建议如下: 6* 如果希望在任务视图中看到一个任务,则建议使用一个UIAbility,多个页面的方式。 7* 如果希望在任务视图中看到多个任务,或者需要同时开启多个窗口,则建议使用多个UIAbility开发不同的模块功能。 8 9本例即为大家介绍如何基于Stage模型下的UIAbility开发,实现UIAbility内和UIAbility间页面的跳转与数据传递的功能。 10 11## 效果呈现 12本例最终效果如下: 13 14 15 16## 运行环境 17本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发: 18- IDE: DevEco Studio 4.0 Beta1 19- SDK: Ohos_sdk_public 4.0.7.5 (API Version 10 Beta1) 20## 实现思路 21本篇案例是基于Stage模型下的UIAbility开发,实现UIAbility内和UIAbility间页面的跳转。 22* UIAbility内页面的跳转: 23 entry模块中,通过添加页面路由router来实现,页面路由router根据页面url找到目标页面,从而实现跳转。 24* UIAbility间页面的跳转--跳转到指定UIAbility的首页: 25 实现UIAbility间页面的跳转,需要启动另外一个UIAbility,可以通过UIAbilityContext的startAbility的方法来完成。 26* UIAbility间页面的跳转--跳转到指定UIAbility的指定页面(非首页): 27 实现跳转到指定UIAbility的指定页面(非首页),就需要在跳转到指定UIAbility的首页的基础上,新建一个Second页面,使用UIAbilityContext.startAbilityForResult来实现。 28## 开发步骤 29由于本例重点介绍UIAbility之间的跳转,所以开发步骤会着重讲解相关实现,不相关的内容不做介绍,全量代码可参考完整代码章节。 301. 从实现效果看,UIAbility之间的跳转,都是通过点击每个页面的button后实现的,因此我们可以先构建一个按钮点击后调用的方法类:ButtonClickMethod。 31 具体代码如下: 32 ```ts 33 // entry/src/main/ets/model/ButtonClickMethod.ets 34 35 ... 36 // 按钮点击后调用的方法类 37 Class ButtonClickMethod{ 38 ... 39 40 } 41 export default new ButtonClickMethod(); 42 ``` 43 442. UIAbility内页面的跳转。 45 * 实现UIAbility内页面的跳转,首先构建Index页面,Index页面由一个Image组件、两个Text组件、三个Button组件组成。 46 具体代码如下: 47 ```ts 48 // entry/src/main/ets/pages/Index.ets 49 50 @Entry 51 @Component 52 struct Index { 53 @State text: string = ''; 54 55 build() { 56 Column() { 57 Image($r('app.media.right')) 58 ... 59 Text($r('app.string.main_index_page_name')) 60 ... 61 // 条件渲染:当text的值不为空时,显示该组件 62 if (this.text !== '') { 63 Text(this.text) 64 ... 65 } 66 // 导航到EntryAbility的Second Page按钮 67 Button($r('app.string.to_main_second_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 68 ... 69 // 导航到SecondAbility的Index Page按钮 70 Button($r('app.string.to_second_index_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 71 ... 72 // 导航到SecondAbility的Index Page按钮 73 Button($r('app.string.to_second_second_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 74 ... 75 } 76 ... 77 } 78 } 79 ``` 80 * 构建Second页面,该页面由一个Image组件、两个Text组件、一个Button组件组成。 81 具体代码如下: 82 ```ts 83 // entry/src/main/ets/pages/Second.ets 84 85 @Entry 86 @Component 87 struct Second { 88 ... 89 90 build() { 91 Column() { 92 Image($r('app.media.left')) 93 ... 94 95 Text($r('app.string.main_second_page_name')) 96 ... 97 98 Text(`${this.src}:${this.count}`) 99 ... 100 101 // 返回到EntryAbility的Index Page按钮 102 Button($r('app.string.back_main_index_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 103 ... 104 } 105 ... 106 } 107 } 108 ``` 109 * entry模块的Index和Second页面之间的跳转以及数据的传递,需要通过router来实现。 110 * 从EntryAbility首页跳转到Second页面: 111 1. 导入router模块, 向按钮点击后调用的方法类ButtonClickMethod中添加toEntryAbilitySecond方法,使用router.pushUrl实现跳转,同时通过params来向新页面传入参数。 112 具体代码如下: 113 ```ts 114 // entry/src/main/ets/model/ButtonClickMethod.ets 115 import router from '@ohos.router'; 116 117 // 按钮点击后调用的方法类 118 Class ButtonClickMethod{ 119 // 导航entry模块的Second页面 120 toEntryAbilitySecond() { 121 router.pushUrl({ 122 url: 'pages/Second', 123 params: { 124 src: textMessage, 125 count: CommonConstants.NUM_VALUES[0] 126 } 127 }); 128 } 129 ... 130 131 } 132 export default new ButtonClickMethod(); 133 ``` 134 2. 点击“导航到EntryAbility的Second Page”按钮后,调用ButtonClickMethod类中的toEntryAbilitySecond方法,跳转到EntryAbility的Second页面。 135 具体代码如下: 136 ```ts 137 // entry/src/main/ets/pages/Index.ets 138 ... 139 140 @Entry 141 @Component 142 struct Index { 143 @State text: string = ''; 144 @State bottomMargin: string = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 145 146 build() { 147 Column() { 148 Image($r('app.media.right')) 149 ... 150 Text($r('app.string.main_index_page_name')) 151 ... 152 // 条件渲染:当text的值不为空时,显示该组件 153 if (this.text !== '') { 154 Text(this.text) 155 ... 156 } 157 158 Button($r('app.string.to_main_second_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 159 ... 160 .onClick(() => { 161 // 导航到EntryAbility的Second Page 162 ButtonClickMethod.toSecondAbilityIndex(context); 163 this.text = ''; 164 this.bottomMargin = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 165 }) 166 167 Button($r('app.string.to_second_index_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 168 ... 169 170 Button($r('app.string.to_second_second_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 171 ... 172 } 173 ... 174 } 175 } 176 ``` 177 * 从entry模块的EntryAbility的Second页面返回至EntryAbility首页: 178 向EntryAbility的Second页面导入router模块,同时给button添加oncClick事件,使用router.back实现返回至EntryAbility的index页面。 179 具体代码如下: 180 ```ts 181 // entry/src/main/ets/pages/Second.ets 182 import router from '@ohos.router'; 183 184 @Entry 185 @Component 186 struct Second { 187 ... 188 189 build() { 190 Column() { 191 Image($r('app.media.left')) 192 ... 193 194 Text($r('app.string.main_second_page_name')) 195 ... 196 197 Text(`${this.src}:${this.count}`) 198 ... 199 200 Button($r('app.string.back_main_index_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 201 ... 202 .onClick(() => { 203 // 返回到EntryAbility的Index Page 204 router.back(); 205 }) 206 } 207 ... 208 } 209 } 210 ``` 211 2123. 跳转到指定的UIAbility的首页。 213 * 实现跳转到指定UIAbility的首页,先构建另外一个模块,方法如下: 214 在“Project”窗口,右键点击“entry 文件夹”,选择“New > Module > Empty Ability > Next”,在“Module name”中给新建的模块命名为“device”,点击“Next”,在“Ability name”中给新建模块的Ability命名为“SecondAbility”,点击“Finish”。可以看到文件目录结构如下: 215  216 * 构建device模块下SecondAbility的Index页面,该页面由一个Image组件、两个Text组件、一个Button组件组成。 217 具体代码如下: 218 ```ts 219 // device/src/main/ets/pages/Index.ets 220 221 @Entry 222 @Component 223 struct Index { 224 ... 225 226 build() { 227 Column() { 228 Image($r('app.media.left')) 229 ... 230 231 Text($r('app.string.second_index_page_name')) 232 ... 233 234 Text(`${this.src}:${this.count}`) 235 ... 236 237 // 停止SecondAbility自身按钮 238 Button($r('app.string.terminate_second_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 239 ... 240 } 241 ... 242 } 243 } 244 ``` 245 * 从entry模块的EntryAbility首页跳转至device模块的SecondAbility首页:需要通过UIAbilityContext的startAbility方法来实现。 246 1. 在EntryAbility的Index页面获取UIAbilityContext。 247 > 使用UIAbilityContext中的方法,需要在对应的页面获取相应的UIAbilityContext。 248 249 具体代码如下: 250 ```ts 251 // entry/src/main/ets/pages/Index.ets 252 ... 253 // 获取UIAbilityContext 254 let context = getContext(this); 255 ... 256 ``` 257 2. 在EntryAbility的Index页面中,点击“导航到SecondAbility的Index Page”按钮后,调用ButtonClickMethod类中的toSecondAbilityIndex方法,拉起SecondAbility的Index页面,同时通过params来向新页面传入参数。 258 * 向ButtonClickMethod类中添加toSecondAbilityIndex方法。 259 具体代码如下: 260 ```ts 261 // entry/src/main/ets/model/ButtonClickMethod.ets 262 import router from '@ohos.router'; 263 import Logger from '../common/utils/Logger'; 264 265 // 按钮点击后调用的方法类 266 Class ButtonClickMethod{ 267 ... 268 // 导航device模块的Index页面 269 toSecondAbilityIndex(context) { 270 let want = { 271 'deviceId': '', 272 'bundleName': 'com.example.uiability', 273 'abilityName': 'SecondAbility', 274 'moduleName':'device', 275 'parameters': { 276 src: textMessage, 277 count: 45 278 } 279 }; 280 context.startAbility(want).then(() => { 281 Logger.info(CommonConstants.TAG, `start second ability index page succeed with ${JSON.stringify(want)}`); 282 }).catch((error) => { 283 Logger.error(CommonConstants.TAG, `start second ability index page failedwith ${error.code}`); 284 }); 285 } 286 ... 287 } 288 export default new ButtonClickMethod(); 289 ``` 290 * 在EntryAbility的Index页面中,给“导航到SecondAbility的Index Page”按钮添加onClick事件,调用ButtonClickMethod类中的toSecondAbilityIndex方法,实现到SecondAbility首页的跳转。 291 具体代码如下: 292 ```ts 293 // entry/src/main/ets/pages/Index.ets 294 ... 295 296 // 获取UIAbilityContext 297 let context = getContext(this); 298 299 @Entry 300 @Component 301 struct Index { 302 @State text: string = ''; 303 @State bottomMargin: string = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 304 305 build() { 306 Column() { 307 Image($r('app.media.right')) 308 ... 309 Text($r('app.string.main_index_page_name')) 310 ... 311 // 条件渲染:当text的值不为空时,显示该组件 312 if (this.text !== '') { 313 Text(this.text) 314 ... 315 } 316 317 Button($r('app.string.to_main_second_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 318 ... 319 320 Button($r('app.string.to_second_index_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 321 ... 322 .onClick(() => { 323 // 导航到SecondAbility的Index页面 324 ButtonClickMethod.toSecondAbilityIndex(context); 325 this.text = ''; 326 this.bottomMargin = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 327 }) 328 329 Button($r('app.string.to_second_second_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 330 ... 331 } 332 ... 333 } 334 } 335 ``` 336 * 在SecondAbility的Index页面,获取从EntryAbility的Index页面传递过来的自定义参数,并用一个Text文本展示从Index页面传递过来的数据。 337 具体代码如下: 338 ```ts 339 // device/src/main/ets/pages/Index.ets 340 ... 341 @Entry 342 @Component 343 struct Index { 344 // 获取从EntryAbility的Index页面传递过来的自定义参数 345 @State src: string = globalThis?.secondAbilityWant?.parameters?.src ?? '-'; 346 @State count: number = globalThis?.secondAbilityWant?.parameters?.count ?? 0; 347 348 build() { 349 Column() { 350 Image($r('app.media.left')) 351 ... 352 Text($r('app.string.second_index_page_name')) 353 ... 354 // 用一个Text文本展示从Index页面传递过来的数据 355 Text(`${this.src}:${this.count}`) 356 ... 357 // 停止SecondAbility自身按钮 358 Button($r('app.string.terminate_second_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 359 ... 360 } 361 ... 362 } 363 } 364 ``` 365 366 * 从device模块的SecondAbility首页返回到entry模块的EntryAbility首页:通过点击device模块的Index页面的“停止SecondAbility自身”按钮,使用UIAbilityContext.terminateSelf方法手动销毁Ability。 367 1. 给ButtonClickMethod类中添加toSecondAbilityIndex方法。 368 具体代码如下: 369 ```ts 370 // entry/src/main/ets/model/ButtonClickMethod.ets 371 import router from '@ohos.router'; 372 import Logger from '../common/utils/Logger'; 373 374 // 按钮点击后调用的方法类 375 Class ButtonClickMethod{ 376 ... 377 // 停止SecondAbility自身 378 terminateSecondAbility(context) { 379 context.terminateSelf().then(() => { 380 Logger.info(CommonConstants.TAG, 'terminate second ability self succeed'); 381 }).catch((error) => { 382 Logger.error(CommonConstants.TAG, `terminate second ability self failed with ${error.code}`); 383 }); 384 } 385 ... 386 } 387 export default new ButtonClickMethod(); 388 ``` 389 2. 在SecondAbility的Index页面中,给“停止SecondAbility自身”按钮添加onClick事件,调用ButtonClickMethod类中的terminateSecondAbility方法,使用UIAbilityContext.terminateSelf方法手动销毁Ability,从而实现从SecondAbility的Index页面返回至entry的Index页面。 390 具体代码如下: 391 ```ts 392 // device/src/main/ets/model/Index.ets 393 394 let context = getContext(this); 395 ... 396 @Entry 397 @Component 398 struct Index { 399 // 获取从EntryAbility的Index页面传递过来的自定义参数 400 @State src: string = globalThis?.secondAbilityWant?.parameters?.src ?? '-'; 401 @State count: number = globalThis?.secondAbilityWant?.parameters?.count ?? 0; 402 403 build() { 404 Column() { 405 Image($r('app.media.left')) 406 ... 407 Text($r('app.string.second_index_page_name')) 408 ... 409 // 用一个Text文本展示从EntryAbility的Index页面传递过来的数据 410 Text(`${this.src}:${this.count}`) 411 ... 412 413 Button($r('app.string.terminate_second_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 414 ... 415 .onClick(() => { 416 // 停止SecondAbility自身 417 ButtonClickMethod.terminateSecondAbility(context); 418 }) 419 } 420 ... 421 } 422 } 423 ``` 424 4254. 跳转到指定UIAbility的指定页面(非首页)。 426 * 构建device模块下SecondAbility的Second页面。该页面由一个Image组件、两个Text组件、一个Button组件组成。 427 具体代码如下: 428 ```ts 429 // device/src/main/ets/pages/Second.ets 430 431 @Entry 432 @Component 433 struct Index { 434 ... 435 436 build() { 437 Column() { 438 Image($r('app.media.left')) 439 ... 440 441 Text($r('app.string.second_second_page_name')) 442 ... 443 444 // 用一个Text文本展示从EntryAbility的Index页面传递过来的数据 445 Text(`${this.src}:${this.count}`) 446 ... 447 448 // 停止SecondAbility自身且返回结果按钮 449 Button($r('app.string.terminate_second_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 450 ... 451 } 452 ... 453 } 454 } 455 ``` 456 * 从entry模块的EntryAbility的首页跳转至device模块的SecondAbility的Second页面:通过点击“导航到SecondAbility的Second Page”按钮后,调用ButtonClickMethod类中的toSecondAbilitySecond方法,拉起SecondAbility的Second页面。 457 1. 给ButtonClickMethod类中添加toSecondAbilitySecond方法,该方法中使用UIAbilityContext.startAbilityForResult来实现,并获取被拉起侧销毁后的返回结果。可以通过parameters来向被拉起方传递参数。 458 具体代码如下: 459 ```ts 460 // entry/src/main/ets/model/ButtonClickMethod.ets 461 import router from '@ohos.router'; 462 import Logger from '../common/utils/Logger'; 463 464 let currentContext = getContext(this); 465 466 // 按钮点击后调用的方法类 467 Class ButtonClickMethod{ 468 ... 469 // 导航到SecondAbility的Second页面 470 toSecondAbilitySecond(context, callback) { 471 let want = { 472 'deviceId': '', 473 'bundleName': 'com.example.uiability', 474 'abilityName': 'SecondAbility', 475 'moduleName':'device', 476 'parameters': { 477 url: 'pages/Second', 478 src: textMessage, 479 count: 78 480 } 481 }; 482 483 // 被拉起侧销毁后,在startAbilityForResult回调中可以获取到被拉起侧销毁时传递过来的AbilityResult 484 context.startAbilityForResult(want).then((result) => { 485 callback(result); 486 Logger.info(CommonConstants.TAG, `start second ability second page succeed with ${JSON.stringify(want)}`); 487 }).catch((error) => { 488 Logger.error(CommonConstants.TAG, `start second ability second page failed with ${error.code}`); 489 }); 490 } 491 ... 492 } 493 export default new ButtonClickMethod(); 494 ``` 495 2. 在EntryAbility的Index页面中,给“导航到SecondAbility的Second Page”按钮添加onClick事件,调用ButtonClickMethod类中的toSecondAbilityIndex方法,实现到SecondAbility首页的跳转。 496 具体代码如下: 497 ```ts 498 // entry/src/main/ets/pages/Index.ets 499 ... 500 501 // 获取UIAbilityContext 502 let context = getContext(this); 503 504 @Entry 505 @Component 506 struct Index { 507 @State text: string = ''; 508 @State bottomMargin: string = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 509 510 build() { 511 Column() { 512 Image($r('app.media.right')) 513 ... 514 Text($r('app.string.main_index_page_name')) 515 ... 516 // 条件渲染:当text的值不为空时,显示该组件 517 if (this.text !== '') { 518 Text(this.text) 519 ... 520 } 521 522 Button($r('app.string.to_main_second_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 523 ... 524 525 Button($r('app.string.to_second_index_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 526 ... 527 528 Button($r('app.string.to_second_second_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 529 ... 530 .onClick(() => { 531 this.text = ''; 532 this.bottomMargin = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 533 534 // 导航到SecondAbility的Second页面 535 ButtonClickMethod.toSecondAbilitySecond(context, (abilityResult) => { 536 // 获取SecondAbility被销毁时传递的abilityResult 537 if (abilityResult.resultCode === CommonConstants.RESULT_CODE) { 538 let src: string = abilityResult?.want?.parameters?.src ?? '-'; 539 let count: number = abilityResult?.want?.parameters?.count ?? 0; 540 this.text = `${src}:${count}`; 541 this.bottomMargin = StyleConstants.BUTTON_MARGIN_BOTTOM; 542 } 543 }); 544 }) 545 } 546 ... 547 } 548 } 549 ``` 550 * 从device模块的SecondAbility的Second页面,返回至entry模块的EntryAbility首页:通过点击“停止SecondAbility自身并返回结果”按钮,调用ButtonClickMethod类中的terminateSecondAbilityForResult方法,使用UIAbilityContext.terminateSelfWithResult方法,同时传入不同的resultCode和want,手动销毁Ability,成功后拉起侧会收到abilityResult的值, 通过Text的方式显示在界面上,从而实现从SecondAbility的Second页面返回至entry的Index页面。 551 1. 给ButtonClickMethod类中添加terminateSecondAbilityForResult方法。 552 具体代码如下: 553 ```ts 554 // entry/src/main/ets/model/ButtonClickMethod.ets 555 import router from '@ohos.router'; 556 import Logger from '../common/utils/Logger'; 557 558 // 按钮点击后调用的方法类 559 Class ButtonClickMethod{ 560 ... 561 // 停止SecondAbility自身 562 terminateSecondAbilityForResult(context) { 563 let abilityResult = { 564 resultCode: CommonConstants.RESULT_CODE, 565 want: { 566 'parameters': { 567 src: returnMessage, 568 count: 99 569 } 570 } 571 }; 572 573 // 停止SecondAbility自身,并将abilityResult返回给startAbilityForResult接口调用方 574 context.terminateSelfWithResult(abilityResult).then(() => { 575 Logger.info(CommonConstants.TAG, `terminate second ability self succeed with ${JSON.stringify(abilityResult)}`); 576 }).catch((error) => { 577 Logger.error(CommonConstants.TAG, `terminate second ability self failed with ${error.code}`); 578 }); 579 } 580 ... 581 } 582 export default new ButtonClickMethod(); 583 ``` 584 2. 在SecondAbility的Index页面中,给“停止SecondAbility自身并返回结果”按钮添加onClick事件,调用ButtonClickMethod类中的terminateSecondAbilityForResult方法,手动销毁自身Ability。 585 具体代码如下: 586 ```ts 587 // device/src/main/ets/pages/Second.ets 588 let context = getContext(this); 589 590 @Entry 591 @Component 592 struct Second { 593 // 用来接收parameters参数传过来的值 594 @State src: string = globalThis?.secondAbilityWant?.parameters?.src ?? '-'; 595 @State count: number = globalThis?.secondAbilityWant?.parameters?.count ?? 0; 596 597 build() { 598 Column() { 599 Image($r('app.media.left')) 600 ... 601 602 Text($r('app.string.second_second_page_name')) 603 ... 604 605 Text(`${this.src}:${this.count}`) 606 .. 607 608 // 停止SecondAbility自身且返回结果按钮 609 Button($r('app.string.terminate_second_for_result_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 610 ... 611 .onClick(() => { 612 // 停止SecondAbility自身且返回结果. 613 ButtonClickMethod.terminateSecondAbilityForResult(context); 614 }) 615 } 616 ... 617 } 618 } 619 ``` 620## 完整代码 621本例完整代码如下: 6221. entry模块的代码: 623 * 公共常量类:entry/src/main/ets/common/constants/CommonConstants.ets 624 具体代码如下: 625 ```ts 626 class CommonConstants { 627 TAG = '[ButtonClickMethod.ts]'; 628 RESULT_CODE = 100; 629 } 630 export default new CommonConstants(); 631 632 ``` 633 * 样式常量类:entry/src/main/ets/common/constants/StyleConstants.ets 634 具体代码如下: 635 ```ts 636 class StyleConstants { 637 IMAGE_WIDTH = '78%'; 638 639 IMAGE_HEIGHT = '25%'; 640 641 IMAGE_MARGIN_TOP = '140vp'; 642 643 IMAGE_MARGIN_BOTTOM = '55vp'; 644 645 MAIN_INDEX_TEXT_MARGIN_BOTTOM = '148vp'; 646 647 BUTTON_WIDTH = '87%'; 648 649 BUTTON_HEIGHT = '5%'; 650 651 BUTTON_MARGIN_BOTTOM = '12vp'; 652 653 MAIN_INDEX_BUTTON_MARGIN_BOTTOM = '179vp'; 654 655 TEXT_MARGIN_BOTTOM = '250vp'; 656 657 FULL_PERCENT = '100%'; 658 659 FONT_SIZE_BIG = 20; 660 661 FONT_WEIGHT = 500; 662 663 FONT_SIZE_SMALL = 16; 664 665 OPACITY = 0.6; 666 } 667 export default new StyleConstants(); 668 ``` 669 * 按钮点击后调用的方法类:entry/src/main/ets/model/ButtonClickMethod.ets 670 具体代码如下: 671 ```ts 672 import router from '@ohos.router'; 673 import Logger from '../common/utils/Logger'; 674 import CommonConstants from '../common/constants/CommonConstants'; 675 676 let currentContext = getContext(this); 677 let textMessage: string = currentContext.resourceManager.getStringSync($r('app.string.text_message')); 678 let returnMessage: string = currentContext.resourceManager.getStringSync($r('app.string.return_message')); 679 680 // 按钮点击后调用的方法类 681 class ButtonClickMethod { 682 // 导航entry模块的Second页面 683 toEntryAbilitySecond() { 684 router.pushUrl({ 685 url: 'pages/Second', 686 params: { 687 src: textMessage, 688 count: 12 689 } 690 }); 691 } 692 693 // 导航device模块的Index页面 694 toSecondAbilityIndex(context) { 695 let want = { 696 'deviceId': '', 697 'bundleName': 'com.example.uiability', 698 'abilityName': 'SecondAbility', 699 'moduleName':'device', 700 701 'parameters': { 702 src: textMessage, 703 count: 45 704 } 705 }; 706 context.startAbility(want).then(() => { 707 Logger.info(CommonConstants.TAG, `start second ability index page succeed with ${JSON.stringify(want)}`); 708 }).catch((error) => { 709 Logger.error(CommonConstants.TAG, `start second ability index page failedwith ${error.code}`); 710 }); 711 } 712 713 // 导航到SecondAbility的Second页面 714 toSecondAbilitySecond(context, callback) { 715 let want = { 716 'deviceId': '', 717 'bundleName': 'com.example.uiability', 718 'abilityName': 'SecondAbility', 719 'moduleName':'device', 720 'parameters': { 721 url: 'pages/Second', 722 src: textMessage, 723 count: 78 724 } 725 }; 726 727 // 被拉起侧销毁后,在startAbilityForResult回调中可以获取到被拉起侧销毁时传递过来的AbilityResult 728 context.startAbilityForResult(want).then((result) => { 729 callback(result); 730 Logger.info(CommonConstants.TAG, `start second ability second page succeed with ${JSON.stringify(want)}`); 731 }).catch((error) => { 732 Logger.error(CommonConstants.TAG, `start second ability second page failed with ${error.code}`); 733 }); 734 } 735 736 // 停止SecondAbility自身 737 terminateSecondAbility(context) { 738 context.terminateSelf().then(() => { 739 Logger.info(CommonConstants.TAG, 'terminate second ability self succeed'); 740 }).catch((error) => { 741 Logger.error(CommonConstants.TAG, `terminate second ability self failed with ${error.code}`); 742 }); 743 } 744 745 // 停止SecondAbility自身并返回结果 746 terminateSecondAbilityForResult(context) { 747 let abilityResult = { 748 resultCode: CommonConstants.RESULT_CODE, 749 want: { 750 'parameters': { 751 src: returnMessage, 752 count: 99 753 } 754 } 755 }; 756 757 // 停止SecondAbility自身,并将abilityResult返回给startAbilityForResult接口调用方 758 context.terminateSelfWithResult(abilityResult).then(() => { 759 Logger.info(CommonConstants.TAG, `terminate second ability self succeed with ${JSON.stringify(abilityResult)}`); 760 }).catch((error) => { 761 Logger.error(CommonConstants.TAG, `terminate second ability self failed with ${error.code}`); 762 }); 763 } 764 } 765 766 export default new ButtonClickMethod(); 767 ``` 768 * EntryAbility的Index页面:entry/src/main/ets/pages/Index.ets 769 具体代码如下: 770 ```ts 771 import ButtonClickMethod from '../model/ButtonClickMethod'; 772 import StyleConstants from '../common/constants/StyleConstants'; 773 import CommonConstants from '../common/constants/CommonConstants'; 774 775 // 获取EntryAbility的UIAbilityContext 776 let context = getContext(this); 777 778 @Entry 779 @Component 780 struct Index { 781 @State text: string = ''; 782 @State bottomMargin: string = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 783 784 build() { 785 Column() { 786 Image($r('app.media.right')) 787 .objectFit(ImageFit.Contain) 788 .width(StyleConstants.IMAGE_WIDTH) 789 .height(StyleConstants.IMAGE_HEIGHT) 790 .margin({ 791 top: StyleConstants.IMAGE_MARGIN_TOP, 792 bottom: StyleConstants.IMAGE_MARGIN_BOTTOM 793 }) 794 795 Text($r('app.string.main_index_page_name')) 796 .fontColor('#000') 797 .fontSize(StyleConstants.FONT_SIZE_BIG) 798 .fontWeight(StyleConstants.FONT_WEIGHT) 799 .margin({ bottom: this.bottomMargin }) 800 801 // 条件渲染:当text的值不为空时,显示该组件 802 if (this.text !== '') { 803 Text(this.text) 804 .fontColor('#000') 805 .fontSize(StyleConstants.FONT_SIZE_SMALL) 806 .opacity(StyleConstants.OPACITY) 807 .margin({ bottom: StyleConstants.MAIN_INDEX_TEXT_MARGIN_BOTTOM }) 808 } 809 810 // 导航到EntryAbility的Second Page按钮 811 Button($r('app.string.to_main_second_page_btn_text'),{ type: ButtonType.Capsule, stateEffect: true }) 812 .backgroundColor($r('app.color.button_background_color')) 813 .width(StyleConstants.BUTTON_WIDTH) 814 .height(StyleConstants.BUTTON_HEIGHT) 815 .margin({ bottom: StyleConstants.BUTTON_MARGIN_BOTTOM }) 816 .onClick(() => { 817 // 导航到EntryAbility的Second page 818 ButtonClickMethod.toEntryAbilitySecond(); 819 this.text = ''; 820 this.bottomMargin = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 821 }) 822 823 // 导航到SecondAbility的Index Page按钮 824 Button($r('app.string.to_second_index_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 825 .backgroundColor($r('app.color.button_background_color')) 826 .width(StyleConstants.BUTTON_WIDTH) 827 .height(StyleConstants.BUTTON_HEIGHT) 828 .margin({ bottom: StyleConstants.BUTTON_MARGIN_BOTTOM }) 829 .onClick(() => { 830 // 导航到SecondAbility的Index Page 831 ButtonClickMethod.toSecondAbilityIndex(context); 832 this.text = ''; 833 this.bottomMargin = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 834 }) 835 836 // 导航到SecondAbility的Index Page按钮 837 Button($r('app.string.to_second_second_page_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 838 .backgroundColor($r('app.color.button_background_color')) 839 .width(StyleConstants.BUTTON_WIDTH) 840 .height(StyleConstants.BUTTON_HEIGHT) 841 .onClick(() => { 842 this.text = ''; 843 this.bottomMargin = StyleConstants.MAIN_INDEX_BUTTON_MARGIN_BOTTOM; 844 // 导航到SecondAbility的Second Page 845 ButtonClickMethod.toSecondAbilitySecond(context, (abilityResult) => { 846 // 获取SecondAbility被销毁时传递的abilityResult 847 if (abilityResult.resultCode === CommonConstants.RESULT_CODE) { 848 let src: string = abilityResult?.want?.parameters?.src ?? '-'; 849 let count: number = abilityResult?.want?.parameters?.count ?? 0; 850 this.text = `${src}:${count}`; 851 this.bottomMargin = StyleConstants.BUTTON_MARGIN_BOTTOM; 852 } 853 }); 854 }) 855 } 856 .width(StyleConstants.FULL_PERCENT) 857 .height(StyleConstants.FULL_PERCENT) 858 .backgroundColor($r('app.color.background_color')) 859 } 860 } 861 ``` 862 * EntryAbility的Second页面:entry/src/main/ets/pages/Second.ets 863 具体代码如下: 864 ```ts 865 import router from '@ohos.router'; 866 import StyleConstants from '../common/constants/StyleConstants'; 867 868 @Entry 869 @Component 870 struct Second { 871 @State src: string = router?.getParams()?.['src'] ?? '-'; 872 @State count: number = router?.getParams()?.['count'] ?? 0; 873 874 build() { 875 Column() { 876 Image($r('app.media.left')) 877 .objectFit(ImageFit.Contain) 878 .width(StyleConstants.IMAGE_WIDTH) 879 .height(StyleConstants.IMAGE_HEIGHT) 880 .margin({ 881 top: StyleConstants.IMAGE_MARGIN_TOP, 882 bottom: StyleConstants.IMAGE_MARGIN_BOTTOM 883 }) 884 885 Text($r('app.string.main_second_page_name')) 886 .fontColor('#000') 887 .fontSize(StyleConstants.FONT_SIZE_BIG) 888 .fontWeight(StyleConstants.FONT_WEIGHT) 889 .margin({ bottom: StyleConstants.BUTTON_MARGIN_BOTTOM }) 890 891 // 用一个Text文本展示从EntryAbility的Index页面传递过来的数据 892 Text(`${this.src}:${this.count}`) 893 .fontColor('ccc') 894 .fontSize(StyleConstants.FONT_SIZE_SMALL) 895 .opacity(StyleConstants.OPACITY) 896 .margin({ bottom: StyleConstants.TEXT_MARGIN_BOTTOM }) 897 898 // 返回到EntryAbility的Index Page按钮 899 Button($r('app.string.back_main_index_page_btn_text'),{ type: ButtonType.Capsule, stateEffect: true }) 900 .backgroundColor($r('app.color.button_background_color')) 901 .width(StyleConstants.BUTTON_WIDTH) 902 .height(StyleConstants.BUTTON_HEIGHT) 903 .onClick(() => { 904 // 返回到EntryAbility的Index Page 905 router.back(); 906 }) 907 } 908 .width(StyleConstants.FULL_PERCENT) 909 .height(StyleConstants.FULL_PERCENT) 910 .backgroundColor($r('app.color.background_color')) 911 } 912 } 913 ``` 9142. device模块的代码: 915 * SecondAbility的Index页面:device/src/main/ets/pages/Index.ets 916 具体代码如下: 917 ```ts 918 import ButtonClickMethod from '../../../../../entry/src/main/ets/model/ButtonClickMethod'; 919 import StyleConstants from '../../../../../entry/src/main/ets/common/constants/StyleConstants'; 920 921 // 获取SecondAbility的UIAbilityContext 922 let context = getContext(this); 923 924 @Entry 925 @Component 926 struct Index { 927 // 获取从EntryAbility的Index页面传递过来的自定义参数 928 @State src: string = globalThis?.secondAbilityWant?.parameters?.src ?? '-'; 929 @State count: number = globalThis?.secondAbilityWant?.parameters?.count ?? 0; 930 931 build() { 932 Column() { 933 Image($r('app.media.left')) 934 .objectFit(ImageFit.Contain) 935 .width(StyleConstants.IMAGE_WIDTH) 936 .height(StyleConstants.IMAGE_HEIGHT) 937 .margin({ 938 top: StyleConstants.IMAGE_MARGIN_TOP, 939 bottom: StyleConstants.IMAGE_MARGIN_BOTTOM 940 }) 941 942 // 用一个Text文本展示从EntryAbility的Index页面传递过来的数据 943 Text($r('app.string.second_index_page_name')) 944 .fontColor('#000') 945 .fontSize(StyleConstants.FONT_SIZE_BIG) 946 .fontWeight(StyleConstants.FONT_WEIGHT) 947 .margin({ bottom: StyleConstants.BUTTON_MARGIN_BOTTOM }) 948 949 // 用一个Text文本展示从Index页面传递过来的数据 950 Text(`${this.src}:${this.count}`) 951 .fontColor('#000') 952 .fontSize(StyleConstants.FONT_SIZE_SMALL) 953 .opacity(StyleConstants.OPACITY) 954 .margin({ bottom: StyleConstants.TEXT_MARGIN_BOTTOM }) 955 956 // 停止SecondAbility自身按钮 957 Button($r('app.string.terminate_second_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 958 .backgroundColor($r('app.color.button_background_color')) 959 .width(StyleConstants.BUTTON_WIDTH) 960 .height(StyleConstants.BUTTON_HEIGHT) 961 .onClick(() => { 962 // 停止SecondAbility自身 963 ButtonClickMethod.terminateSecondAbility(context); 964 }) 965 } 966 .width(StyleConstants.FULL_PERCENT) 967 .height(StyleConstants.FULL_PERCENT) 968 .backgroundColor($r('app.color.background_color')) 969 } 970 } 971 ``` 972 * SecondAbility的Second页面:device/src/main/ets/pages/Second.ets 973 具体代码如下: 974 ```ts 975 import ButtonClickMethod from '../../../../../entry/src/main/ets/model/ButtonClickMethod'; 976 import StyleConstants from '../../../../../entry/src/main/ets/common/constants/StyleConstants'; 977 978 let context = getContext(this); 979 980 @Entry 981 @Component 982 struct Second { 983 // 用来接收parameters参数传过来的值 984 @State src: string = globalThis?.secondAbilityWant?.parameters?.src ?? '-'; 985 @State count: number = globalThis?.secondAbilityWant?.parameters?.count ?? 0; 986 987 build() { 988 Column() { 989 Image($r('app.media.left')) 990 .objectFit(ImageFit.Contain) 991 .width(StyleConstants.IMAGE_WIDTH) 992 .height(StyleConstants.IMAGE_HEIGHT) 993 .margin({ 994 top: StyleConstants.IMAGE_MARGIN_TOP, 995 bottom: StyleConstants.IMAGE_MARGIN_BOTTOM 996 }) 997 998 Text($r('app.string.second_second_page_name')) 999 .fontColor('#000') 1000 .fontSize(StyleConstants.FONT_SIZE_BIG) 1001 .fontWeight(StyleConstants.FONT_WEIGHT) 1002 .margin({ bottom: StyleConstants.BUTTON_MARGIN_BOTTOM }) 1003 1004 // 用一个Text文本展示从EntryAbility的Index页面传递过来的数据 1005 Text(`${this.src}:${this.count}`) 1006 .fontColor('#000') 1007 .fontSize(StyleConstants.FONT_SIZE_SMALL) 1008 .opacity(StyleConstants.OPACITY) 1009 .margin({ bottom: StyleConstants.TEXT_MARGIN_BOTTOM }) 1010 1011 // 停止SecondAbility自身且返回结果按钮 1012 Button($r('app.string.terminate_second_for_result_btn_text'), { type: ButtonType.Capsule, stateEffect: true }) 1013 .backgroundColor($r('app.color.button_background_color')) 1014 .width(StyleConstants.BUTTON_WIDTH) 1015 .height(StyleConstants.BUTTON_HEIGHT) 1016 .onClick(() => { 1017 // 停止SecondAbility自身且返回结果 1018 ButtonClickMethod.terminateSecondAbilityForResult(context); 1019 }) 1020 } 1021 .width(StyleConstants.FULL_PERCENT) 1022 .height(StyleConstants.FULL_PERCENT) 1023 .backgroundColor($r('app.color.background_color')) 1024 } 1025 } 1026 ``` 1027 1028## 参考 1029 1030- [UIAbility组件概述](../application-dev/application-models/uiability-overview.md) 1031 1032- [UIAbility组件使用指导](../application-dev/reference/apis-ability-kit/js-apis-app-ability-uiAbility.md) 1033 1034- [UIAbilityContext使用指导](../application-dev/reference/apis-ability-kit/js-apis-inner-application-uiAbilityContext.md) 1035 1036- [router (页面路由)使用指导](../application-dev/reference/apis-arkui/js-apis-router.md) 1037 1038- [Want使用指导](../application-dev/reference/apis-ability-kit/js-apis-application-want.md) 1039