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![UIAbility](figures/UIAbility.gif)
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        ![device-modules](figures/device-module.png)
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