欢迎光临
我们一直在努力

鸿蒙 卡片页面交互:应用页面跳转(一)

本文同步发表于我的微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

   在ArkTS卡片开发中,页面交互是最核心的功能之一。用户点击卡片上的按钮,可以跳转到应用内的指定页面、传递消息给应用、甚至拉起后台服务。

  • 三种事件类型:router、message、call

  • 两种卡片形态:动态卡片(postCardAction)和静态卡片(FormLink)

一、卡片交互

ArkTS卡片提供三种页面交互能力:

交互能力说明
页面跳转 卡片跳转到卡片提供方应用的指定UIAbility
拉起进程 卡片拉起卡片提供方进程
消息传递 卡片与卡片提供方之间的消息通信

卡片形态与对应接口

卡片类型交互接口适用场景
动态卡片 postCardAction 需要动态交互、数据更新的卡片
静态卡片 FormLink 简单展示、无需动态更新的卡片

二、三种事件类型

postCardAction和FormLink均支持以下三种事件类型:

事件类型作用典型场景
router事件 跳转到指定UIAbility 点击卡片进入应用详情页
call事件 拉起UIAbility到后台 音乐播放、后台任务
message事件 触发onFormEvent回调 数据刷新、状态同步

2.1 router事件(页面跳转)

作用:跳转到指定UIAbility(页面)

限制:

  • 非系统应用仅支持跳转到自己应用内的UIAbility

  • 不能跳转到其他应用的页面

典型应用:

  • 相机卡片:点击"拍照"按钮进入相机界面

  • 天气卡片:点击"详情"进入天气预报页面

  • 待办卡片:点击"查看全部"进入待办列表

2.2 call事件(后台拉起)

作用:拉起指定UIAbility到后台

特点:

  • UIAbility在后台运行

  • 可通过UIAbility申请后台长时任务

  • 适合音乐播放、位置跟踪等场景

2.3 message事件(消息传递)

作用:拉起FormExtensionAbility,触发onFormEvent回调

特点:

  • 卡片发送消息给应用

  • 应用在onFormEvent中处理消息

  • 适合数据刷新、状态同步等场景

三、示例:卡片跳转到应用页面(router事件)

示例功能:

  • 卡片上有两个按钮:"FunA页面"和"FunB页面"

  • 点击不同按钮,跳转到应用内不同的页面

  • 通过params传递参数,区分跳转目标

3.1 创建卡片布局

// src/main/ets/widgeteventrouter/pages/WidgetEventRouterCard.ets

@Entry
@Component
struct WidgetEventRouterCard {
build() {
Column() {
// 标题文字
Text($r('app.string.JumpLabel'))
.fontColor('#FFFFFF')
.opacity(0.9)
.fontSize(14)
.margin({ top: '8%', left: '10%' })

// 按钮区域
Row() {
Column() {
// 按钮A:跳转到FunA页面
Button() {
Text($r('app.string.ButtonA_label'))
.fontColor('#45A6F4')
.fontSize(12)
}
.width(120)
.height(32)
.margin({ top: '20%' })
.backgroundColor('#FFFFFF')
.borderRadius(16)
.onClick(() => {
// 发送router事件,携带targetPage=funA
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility', // 目标UIAbility
params: { targetPage: 'funA' } // 自定义参数
});
})

// 按钮B:跳转到FunB页面
Button() {
Text($r('app.string.ButtonB_label'))
.fontColor('#45A6F4')
.fontSize(12)
}
.width(120)
.height(32)
.margin({ top: '8%', bottom: '15vp' })
.backgroundColor('#FFFFFF')
.borderRadius(16)
.onClick(() => {
// 发送router事件,携带targetPage=funB
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { targetPage: 'funB' }
});
})
}
}
.width('100%')
.height('80%')
.justifyContent(FlexAlign.Center)
}
.width('100%')
.height('100%')
.alignItems(HorizontalAlign.Start)
.backgroundImage($r('app.media.CardEvent'))
.backgroundImageSize(ImageSize.Cover)
}
}

说明:

字段说明
action: 'router' 指定事件类型为router
abilityName: 'EntryAbility' 指定要跳转的UIAbility
params 传递自定义参数,用于区分不同按钮

3.2 在UIAbility中处理router事件

// src/main/ets/entryability/EntryAbility.ts

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';

const TAG: string = 'EntryAbility';
const DOMAIN_NUMBER: number = 0xFF00;

export default class EntryAbility extends UIAbility {
private selectPage: string = 'funA'; // 默认页面
private currentWindowStage: window.WindowStage | null = null;

// 1. 首次创建时触发
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(DOMAIN_NUMBER, TAG, `Ability onCreate, ${JSON.stringify(want)}`);

// 解析卡片传递的参数
if (want?.parameters?.params) {
// want.parameters.params 对应 postCardAction() 中的 params
let params: Record<string, Object> = JSON.parse(want.parameters.params as string);
this.selectPage = params.targetPage as string;
hilog.info(DOMAIN_NUMBER, TAG, `onCreate selectPage: ${this.selectPage}`);
}
}

// 2. 如果UIAbility已在后台运行,收到router事件后触发
onNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {
hilog.info(DOMAIN_NUMBER, TAG, `onNewWant Want: ${JSON.stringify(want)}`);

// 解析卡片传递的参数
if (want?.parameters?.params) {
let params: Record<string, Object> = JSON.parse(want.parameters.params as string);
this.selectPage = params.targetPage as string;
hilog.info(DOMAIN_NUMBER, TAG, `onNewWant selectPage: ${this.selectPage}`);
}

// 重新加载页面
if (this.currentWindowStage !== null) {
this.onWindowStageCreate(this.currentWindowStage);
}
}

// 3. 窗口创建时加载对应页面
onWindowStageCreate(windowStage: window.WindowStage): void {
let targetPage: string;

// 根据selectPage的值,选择不同的页面
switch (this.selectPage) {
case 'funA':
targetPage = 'funpages/FunA';
break;
case 'funB':
targetPage = 'funpages/FunB';
break;
default:
targetPage = 'pages/Index';
}

// 保存WindowStage实例
if (this.currentWindowStage === null) {
this.currentWindowStage = windowStage;
}

// 加载目标页面
windowStage.loadContent(targetPage, (err, data) => {
if (err.code) {
hilog.error(DOMAIN_NUMBER, TAG, 'Failed to load the content. Cause: %{public}s',
JSON.stringify(err) ?? '');
return;
}
hilog.info(DOMAIN_NUMBER, TAG, 'Succeeded in loading the content. Data: %{public}s',
JSON.stringify(data) ?? '');
});
}
}

生命周期说明:

回调触发时机
onCreate UIAbility首次创建时触发
onNewWant UIAbility已在后台运行,收到新请求时触发
onWindowStageCreate 窗口创建时触发,用于加载页面

3.3 创建目标页面

FunA.ets

// src/main/ets/funpages/FunA.ets

@Entry
@Component
struct FunA {
build() {
Column() {
// 标题栏
Row() {
Text($r('app.string.ButtonA_label'))
.fontSize(24)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Start)
.margin({
top: 12,
bottom: 11,
right: 24,
left: 24
})
}
.width('100%')
.height(56)
.justifyContent(FlexAlign.Start)

// 空状态图片
Image($r('app.media.pic_empty'))
.width(120)
.height(120)
.margin({ top: 224 })

// 空状态文字
Text($r('app.string.NoContentAvailable'))
.fontSize(14)
.fontColor($r('app.color.text_color'))
.opacity(0.4)
.margin({
top: 8,
bottom: 317,
right: 152,
left: 152
})
}
.width('100%')
.height('100%')
}
}

FunB.ets

// src/main/ets/funpages/FunB.ets

@Entry
@Component
struct FunB {
build() {
Column() {
// 标题栏
Row() {
Text($r('app.string.ButtonB_label'))
.fontSize(24)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Start)
.margin({
top: 12,
bottom: 11,
right: 24,
left: 24
})
}
.width('100%')
.height(56)
.justifyContent(FlexAlign.Start)

// 空状态图片
Image($r('app.media.pic_empty'))
.width(120)
.height(120)
.margin({ top: 224 })

// 空状态文字
Text($r('app.string.NoContentAvailable'))
.fontSize(14)
.fontColor($r('app.color.text_color'))
.opacity(0.4)
.margin({
top: 8,
bottom: 317,
right: 152,
left: 152
})
}
.width('100%')
.height('100%')
}
}

3.4 配置页面路由

在main_pages.json中配置所有页面:

// src/main/resources/base/profile/main_pages.json
{
"src": [
"pages/Index", // 默认主页
"funpages/FunA", // FunA页面
"funpages/FunB" // FunB页面
]
}

3.5 配置资源文件

// src/main/resources/zh_CN/element/string.json
{
"string": [
{
"name": "ButtonA_label",
"value": "FunA页面"
},
{
"name": "ButtonB_label",
"value": "FunB页面"
},
{
"name": "JumpLabel",
"value": "router事件跳转"
},
{
"name": "NoContentAvailable",
"value": "暂无内容"
}
]
}

3.6 运行效果

场景操作结果
卡片初始状态 显示两个按钮:"FunA页面"和"FunB页面"
点击"FunA页面" 卡片发送router事件 应用拉起,跳转到FunA页面
点击"FunB页面" 卡片发送router事件 应用拉起,跳转到FunB页面

四、三种事件对比

4.1 事件类型对比表

对比项router事件call事件message事件
目标 UIAbility(前台) UIAbility(后台) FormExtensionAbility
拉起方式 前台显示 后台运行 后台运行
典型场景 页面跳转 音乐播放 数据刷新
生命周期 onCreate/onNewWant onCreate/onNewWant onFormEvent

4.2 使用示例对比

// router事件 – 跳转到应用页面
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { page: 'detail' }
});

// call事件 – 后台播放音乐
postCardAction(this, {
action: 'call',
abilityName: 'PlayAbility',
params: { song: 'xxx.mp3' }
});

// message事件 – 刷新卡片数据
postCardAction(this, {
action: 'message',
params: { refresh: true }
});

五、注意事项

5.1 限制

限制项说明
跨应用跳转 非系统应用只能跳转到自己应用内的UIAbility
参数传递 params参数需要通过JSON.parse解析
静态卡片 使用FormLink替代postCardAction

5.2 参数解析

// 卡片发送时
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { targetPage: 'funA' }
});

// UIAbility接收时
// want.parameters.params 是JSON字符串,需要解析
let params: Record<string, Object> = JSON.parse(want.parameters.params as string);
let targetPage = params.targetPage; // 获取到 'funA'

5.3 生命周期处理

// 两种情况需要处理:
// 1. 首次启动 – onCreate
// 2. 已存在实例 – onNewWant

onCreate(want) {
// 处理首次启动
}

onNewWant(want) {
// 处理后台唤醒
// 需要重新加载页面
}

总结

ArkTS卡片:

  • 三种事件类型:

    • router:前台页面跳转

    • call:后台服务拉起

    • message:消息传递

  • 两种卡片形态:

    • 动态卡片:postCardAction

    • 静态卡片:FormLink

  • router事件完整流程:

    • 卡片:postCardAction({ action: 'router', abilityName, params })

    • UIAbility:onCreate/onNewWant解析params

    • 根据params加载不同页面

  • 赞(0)
    未经允许不得转载:171主机测评 » 鸿蒙 卡片页面交互:应用页面跳转(一)
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址