【OpenHarmony/HarmonyOs 】从化学学习 App 出发:近场快传、实况窗与全场景智慧学习方案
【OpenHarmony/HarmonyOs 】从化学学习 App 出发:近场快传、实况窗与全场景智慧学习方案
本文基于「化学视界」这个 HarmonyOS 项目展开。当前项目已经具备离线题库、元素周期表、方程式、收藏、错题、成就、学习统计、平板适配等能力。本文重点不是说这些能力已经全部接入系统级近场快传和实况窗,而是说明:在现有项目结构上,如何自然扩展到近场分享、实况窗提醒和全场景智慧学习。🚀
一、项目为什么适合做“全场景学习”?
化学学习有一个明显特点:学习发生在多个碎片场景里。
- 上课时快速查一个元素。
- 做题时查看方程式现象。
- 晚上复习错题。
- 通勤时刷每日一题。
- 平板上横屏看周期表。
- 和同学分享某个元素、方程式或知识点。
这些场景天然适合鸿蒙生态的全场景能力:手机负责随手查,平板负责大屏学习,分享能力负责资料流转,实况窗负责把“正在进行的挑战”留在系统可见位置。
当前项目已经有一些基础:
- 📱
deviceTypes支持phone和tablet。 - 🧩 页面路由清晰,详情页可通过参数打开。
- ⭐ 收藏、错题、成就数据本地保存。
- ⏱️ 限时挑战有明确的倒计时状态。
- 📤 元素详情页已经预留分享按钮。
- ☁️ 配置了备份扩展能力。
模块配置如下:
{
"deviceTypes": [
"phone",
"tablet"
],
"extensionAbilities": [
{
"name": "EntryBackupAbility",
"type": "backup",
"exported": false
}
]
}
这为后续的“全场景智慧生活”扩展打好了底。
二、近场快传:学习内容最小单元化
近场快传的核心不是“传整个 App”,而是传一个清晰、轻量、可被接收方理解的学习对象。
在化学学习 App 里,适合作为分享单元的内容有:
- 一个元素:例如 H、Na、Fe。
- 一个方程式:例如铁与氧气反应。
- 一个知识点:例如质量守恒定律。
- 一组错题:例如今天答错的 5 道题。
- 一次挑战结果:例如 10 题正确 8 题。
项目的元素详情页已经有分享按钮:
Row() {
Image($r('app.media.icon_share'))
.width(20)
.height(20)
.fillColor($r('app.color.text_tab_inactive'))
}
.width(40)
.height(40)
.borderRadius(20)
.backgroundColor($r('app.color.background_color'))
.scale({ x: this.shareButtonScale, y: this.shareButtonScale })
目前这只是一个 UI 入口,后续可以把它接成系统分享、近场快传或自定义 Want 跳转。建议先定义统一的分享数据结构:
interface SharePayload {
type: 'element' | 'equation' | 'knowledge' | 'quizResult';
id: string;
title: string;
summary: string;
deepLink: string;
}
比如元素详情页可以生成:
const payload: SharePayload = {
type: 'element',
id: String(this.elementLocal.number),
title: `${this.elementLocal.name} (${this.elementLocal.symbol})`,
summary: `原子序数 ${this.elementLocal.number},原子量 ${this.elementLocal.atomicMass}`,
deepLink: `huaxue://element/${this.elementLocal.number}`
};
这样不管是系统分享、近场快传,还是未来接入碰一碰、跨设备流转,都可以复用同一份数据。
三、详情页路由:让分享内容可以被精准打开
当前项目详情页通过 router.getParams() 接收参数,例如元素详情:
let params = router.getParams() as Record<string, number>;
if (params && params.elementNumber) {
let el = getElementByNumber(params.elementNumber);
if (el) {
this.element = el;
this.elementLocal = el;
this.isFavorite = isFavorited('element', String(el.number));
}
}
这意味着只要分享内容里带上 elementNumber,接收方就能直接打开对应元素详情页,而不是从首页重新搜索。
推荐的扩展方式:
- 分享时生成
type + id。 - 接收方解析
type。 - 根据类型跳转到对应页面。
- 页面使用原有参数加载内容。
伪代码如下:
function openSharedPayload(payload: SharePayload) {
if (payload.type === 'element') {
router.pushUrl({
url: 'pages/periodic/ElementDetail',
params: { elementNumber: Number(payload.id) }
});
}
if (payload.type === 'equation') {
router.pushUrl({
url: 'pages/equations/EquationDetail',
params: { equationId: Number(payload.id) }
});
}
}
这一步是近场快传体验的关键:传输只是入口,真正影响体验的是“对方打开后是否一步到位”。
四、实况窗:最适合接入限时挑战
在这个项目里,最适合接入实况窗的模块是“限时挑战”。因为它具备典型的实时状态:
- 当前正在答第几题。
- 剩余时间。
- 正确数和错误数。
- 挑战是否结束。
TimeChallengeView 中已经有这些状态:
@State private challengeState: string = 'setup';
@State private questionCount: number = 10;
@State private timePerQuestion: number = 60;
@State private currentIndex: number = 0;
@State private remainingSeconds: number = 0;
@State private correctCount: number = 0;
@State private wrongCount: number = 0;
这几项可以抽象成实况窗展示模型:
interface ChallengeLiveState {
title: string;
progressText: string;
remainingText: string;
scoreText: string;
}
生成状态时可以这样写:
const liveState: ChallengeLiveState = {
title: '化学限时挑战',
progressText: `${this.currentIndex + 1}/${this.questionCount}`,
remainingText: this.remainingSeconds > 0
? `${this.remainingSeconds}s`
: '不限时',
scoreText: `对 ${this.correctCount} · 错 ${this.wrongCount}`
};
接入实况窗后,用户即使暂时切到其他应用,也能看到挑战还剩多久。对学习 App 来说,这种提醒不是打扰,而是帮助用户维持学习节奏。⏱️
五、全场景智慧生活:手机、平板、备份恢复
当前项目已经支持手机和平板:
"deviceTypes": [
"phone",
"tablet"
]
页面里也做了平板断点判断:
const displayClass: display.Display = display.getDefaultDisplaySync();
const density = displayClass.densityDPI;
const screenWidthVp = density > 0
? displayClass.width / density * 160
: 360;
this.isTabletMode = screenWidthVp >= 600;
这让同一套代码能在不同设备上呈现不同密度:
- 手机:单列、轻量、适合随手查。
- 平板:更大字号、更高 TabBar、更宽详情页,适合系统学习。
- 横屏:周期表这类 18 列信息可以展示得更完整。
此外,项目还配置了备份能力:
{
"allowToBackupRestore": true
}
这对学习类 App 很重要。用户的收藏、错题、成就、学习天数都属于长期积累的数据,一旦换设备或重装,如果完全丢失,学习连续性会被打断。
六、收藏与错题:跨设备流转的核心数据
项目的收藏管理器用 AppStorage 存储数据,并通过版本号触发 UI 刷新:
function writeFavorites(items: FavoriteItem[]): void {
AppStorage.setOrCreate(STORAGE_KEY, JSON.stringify(items));
const version = (AppStorage.get<number>(STORAGE_VERSION_KEY) ?? 0) + 1;
AppStorage.setOrCreate(STORAGE_VERSION_KEY, version);
}
错题集也采用轻量存储:
export function addWrongQuestionId(id: number): void {
const ids = readIds();
if (!ids.includes(id)) {
ids.push(id);
writeIds(ids);
}
}
这些数据非常适合做跨设备同步或备份恢复:
- 收藏:用户主动标记的长期兴趣。
- 错题:用户短期学习弱点。
- 成就:用户持续使用的激励系统。
- 学习统计:可以生成个性化学习报告。
如果后续做全场景,可以把它们拆成多个数据域,而不是全部混在一个大 JSON 里。这样更方便做版本迁移和局部同步。
七、近场快传文章里的落地写法
如果你要把这个主题写成 CSDN 文章,不建议只写“鸿蒙支持近场快传”。更推荐按照下面逻辑展开:
- 先说明教育 App 的真实分享场景。
- 再说明项目中已有的分享入口和详情页参数路由。
- 然后定义统一的
SharePayload。 - 最后扩展到系统分享、近场快传、跨设备打开。
这样文章会显得有项目基础,而不是纯概念。
可以这样总结:
近场快传不是简单传文本,而是把学习内容变成“可识别、可跳转、可复习”的结构化对象。
八、实况窗文章里的落地写法
实况窗不要什么都放,最适合展示“正在发生、状态会变化、用户关心结果”的内容。
在本项目中,限时挑战最合适:
- 正在进行。
- 有倒计时。
- 有进度。
- 有结果。
- 用户切出 App 后仍然关心。
实况窗展示内容建议控制在三行以内:
- 标题:化学限时挑战。
- 进度:第 3/10 题。
- 状态:剩余 42 秒,对 2 错 0。
复杂解析、题干、选项不适合放进实况窗。实况窗负责提醒和回流,完整答题仍然回到 App 内完成。
九、总结
「化学视界」当前虽然是一个离线学习工具,但它的模块结构很适合扩展到鸿蒙全场景:
- 📤 元素、方程式、知识点可以做近场快传。
- ⏱️ 限时挑战可以接入实况窗。
- 📱 手机和平板可以共享同一套响应式页面。
- ☁️ 收藏、错题、成就可以通过备份能力延续学习数据。
- 🔗 路由参数可以让分享内容被精准打开。
所以这类项目写鸿蒙新特性文章时,不必强行追求“大而全”。只要从一个真实学习场景切入,把系统能力和项目结构连接起来,就能写出既有技术含量又有产品思考的内容。🌈

更多推荐


所有评论(0)