1# 拉起卡片提供方的UIAbility(router事件)
2
3在动态卡片中使用[postCardAction](../reference/apis-arkui/js-apis-postCardAction.md#postcardaction)接口的router能力,能够快速拉起动态卡片提供方应用的指定UIAbility(页面),因此UIAbility较多的应用往往会通过卡片提供不同的跳转按钮,实现一键直达的效果。例如相机卡片,卡片上提供拍照、录像等按钮,点击不同按钮将拉起相机应用的不同UIAbility,从而提高用户的体验。
4
5![WidgerCameraCard](figures/WidgerCameraCard.png)
6
7> **说明:**
8>
9> 本文主要介绍动态卡片的事件开发。对于静态卡片,请参见[FormLink](../reference/apis-arkui/arkui-ts/ts-container-formlink.md)。
10
11## 开发步骤
121. 创建动态卡片
13
14   在工程的 entry 模块中,新建名为WidgetEventRouterCard的ArkTs卡片。
15
162. 构建ArkTs卡片页面代码布局
17
18   卡片页面布局中有两个按钮,点击其中一个按钮时调用postCardAction向指定UIAbility发送router事件,并在事件内定义需要传递的内容。
19
20    ```ts
21    //src/main/ets/widgeteventroutercard/pages/WidgetEventRouterCard.ets
22    @Entry
23    @Component
24    struct WidgetEventRouterCard {
25      build() {
26        Column() {
27          Text($r('app.string.JumpLabel'))
28            .fontColor('#FFFFFF')
29            .opacity(0.9)
30            .fontSize(14)
31            .margin({ top: '8%', left: '10%' })
32          Row() {
33            Column() {
34              Button() {
35                Text($r('app.string.ButtonA_label'))
36                  .fontColor('#45A6F4')
37                  .fontSize(12)
38              }
39              .width(120)
40              .height(32)
41              .margin({ top: '20%' })
42              .backgroundColor('#FFFFFF')
43              .borderRadius(16)
44              .onClick(() => {
45                postCardAction(this, {
46                  action: 'router',
47                  abilityName: 'EntryAbility',
48                  params: { targetPage: 'funA' }
49                });
50              })
51
52              Button() {
53                Text($r('app.string.ButtonB_label'))
54                  .fontColor('#45A6F4')
55                  .fontSize(12)
56              }
57              .width(120)
58              .height(32)
59              .margin({ top: '8%', bottom: '15vp' })
60              .backgroundColor('#FFFFFF')
61              .borderRadius(16)
62              .onClick(() => {
63                postCardAction(this, {
64                  action: 'router',
65                  abilityName: 'EntryAbility',
66                  params: { targetPage: 'funB' }
67                });
68              })
69            }
70          }.width('100%').height('80%')
71          .justifyContent(FlexAlign.Center)
72        }
73        .width('100%')
74        .height('100%')
75        .alignItems(HorizontalAlign.Start)
76        .backgroundImage($r('app.media.CardEvent'))
77        .backgroundImageSize(ImageSize.Cover)
78      }
79    }
80    ```
81
824. 处理router事件
83
84   在UIAbility中接收router事件并获取参数,根据传递的params不同,选择拉起不同的页面。
85
86     ```ts
87     //src/main/ets/entryability/EntryAbility.ets
88     import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
89     import { window } from '@kit.ArkUI';
90     import { hilog } from '@kit.PerformanceAnalysisKit';
91
92     const TAG: string = 'EntryAbility';
93     const DOMAIN_NUMBER: number = 0xFF00;
94
95     export default class EntryAbility extends UIAbility {
96       private selectPage: string = '';
97       private currentWindowStage: window.WindowStage | null = null;
98
99       onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
100         // 获取router事件中传递的targetPage参数
101         hilog.info(DOMAIN_NUMBER, TAG, `Ability onCreate: ${JSON.stringify(want?.parameters)}`);
102         if (want?.parameters?.params) {
103           // want.parameters.params 对应 postCardAction() 中 params 内容
104           let params: Record<string, Object> = JSON.parse(want.parameters.params as string);
105           this.selectPage = params.targetPage as string;
106           hilog.info(DOMAIN_NUMBER, TAG, `onCreate selectPage: ${this.selectPage}`);
107         }
108       }
109
110       // 如果UIAbility已在后台运行,在收到Router事件后会触发onNewWant生命周期回调
111       onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
112         hilog.info(DOMAIN_NUMBER, TAG, `Ability onNewWant: ${JSON.stringify(want?.parameters)}`);
113         if (want?.parameters?.params) {
114           // want.parameters.params 对应 postCardAction() 中 params 内容
115           let params: Record<string, Object> = JSON.parse(want.parameters.params as string);
116           this.selectPage = params.targetPage as string;
117           hilog.info(DOMAIN_NUMBER, TAG, `onNewWant selectPage: ${this.selectPage}`);
118         }
119         if (this.currentWindowStage !== null) {
120           this.onWindowStageCreate(this.currentWindowStage);
121         }
122       }
123
124       onWindowStageCreate(windowStage: window.WindowStage): void {
125         // Main window is created, set main page for this ability
126         let targetPage: string;
127         // 根据传递的targetPage不同,选择拉起不同的页面
128         switch (this.selectPage) {
129           case 'funA':
130             targetPage = 'pages/FunA'; //与实际的UIAbility页面路径保持一致
131             break;
132           case 'funB':
133             targetPage = 'pages/FunB'; //与实际的UIAbility页面路径保持一致
134             break;
135           default:
136             targetPage = 'pages/Index'; //与实际的UIAbility页面路径保持一致
137         }
138         if (this.currentWindowStage === null) {
139           this.currentWindowStage = windowStage;
140         }
141         windowStage.loadContent(targetPage, (err, data) => {
142           if (err.code) {
143             hilog.error(DOMAIN_NUMBER, TAG, 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
144             return;
145           }
146           hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
147         });
148       }
149     }
150     ```
1515. 创建跳转后的UIAbility页面
152
153   在pages文件夹下新建FunA.etsFunB.ets,构建页面布局。
154
155    ```ts
156   //src/main/ets/pages/FunA.ets
157    @Entry
158    @Component
159    struct FunA {
160      @State message: string = 'Hello World';
161
162      build() {
163        RelativeContainer() {
164          Text(this.message)
165            .id('HelloWorld')
166            .fontSize(50)
167            .fontWeight(FontWeight.Bold)
168            .alignRules({
169              center: { anchor: '__container__', align: VerticalAlign.Center },
170              middle: { anchor: '__container__', align: HorizontalAlign.Center }
171            })
172        }
173        .height('100%')
174        .width('100%')
175      }
176    }
177    ```
178
1796. 注册UIAbility页面
180
181   打开main_pages.json,将新建的FunA.etsFunB.ets正确注册在src数组中。
182   ```ts
183   //src/main/resources/base/profile/main_pages.json
184   {
185     "src": [
186       "pages/Index",
187       "pages/FunA",
188       "pages/FunB"
189     ]
190   }
191    ```