基于 Harmony 6.0 应用的宠物寄养预约系统实现

前言

养宠人最大的痛点之一是出差或旅游时"毛孩子放谁家"。传统宠物店寄养空间有限、环境嘈杂、价格也不便宜,于是"家庭式寄养"在国内兴起——把宠物寄给家庭主人,用一个二级页可视化整个寄养过程。这种产品 UI 上的关键词是"温暖、放心、可视化",必须让用户在第一屏就感受到"我把毛孩子交给这个 App 不会出错"。Harmony 6.0 时代,宠物寄养这种"信任 + 可视化"双重诉求的应用迎来了一些新的能力红利——分布式摄像头能力让宠主能在自己手机上实时看到寄养家庭的画面、运动手表能监测宠物的心跳、桌面服务卡片能让宠主一眼看到"我家狗今天活动了多久"。这些都不是单纯的 UI 创新,而是鸿蒙在多设备协同上独有的能力外溢。本文用 Flutter 实现一个 Harmony 6.0 端的宠物寄养预约首页,纯 UI、零依赖,作为本系列实战的中间一篇。
在这里插入图片描述

背景

宠物类 App 几乎清一色用粉色或橙色或绿色作为暖色主色,避免冷色给人"冰冷"的印象。本项目首页 5 个模块:渐变 Header、我的宠物(头像组+添加)、4 类服务入口、附近寄养家庭列表(评分+起价+预约)、寄养中订单卡片。橙色 #F97316 作为主色,象征宠物毛发的温暖色调;辅以青色 #06B6D4 做服务图标的多样化。Harmony 6.0 在橙色和粉色系下的渲染表现非常细腻,配合 Flutter 自绘的圆角和阴影,整页能呈现出"放心、温暖、专业"的氛围。从产品角度,宠物寄养应用的复杂度高于一般本地服务——它涉及"宠主、宠物、寄养家庭"三方,每一方都有独立的画像、评价、信任度需要管理。鸿蒙 6.0 在这块的能力栈非常合适:分布式数据让"我家宠物档案、我的预约订单、寄养家庭信息"在多端同步;统一推送让"喂食提醒、运动报告、回家通知"按时序触达;HMS Health Kit 甚至能接入宠物可穿戴设备的健康数据。这些能力让宠物 App 不再是简单的"列表 + 预约",而是真正进化成一种"宠物生活操作系统"。

Flutter × Harmony 6.0 跨端开发介绍

本项目沿用熟悉的 Flutter × Harmony 6.0 工程结构:lib 承担所有 Dart 代码,ohos 承担鸿蒙端壳工程。运行命令 flutter run -d ohos 一行解决打包推送。本系列继续坚守"零三方依赖、纯 Material 容器"的极简哲学,让代码可以五年十年都能稳定 build。鸿蒙 6.0 在橙色这种暖色调上的渲染对 OLED 屏特别友好,无明显塑料感和过曝。Skia 引擎对带圆角 + 渐变 + 透明叠加的卡片渲染极其稳定,本页大量使用的 withValues(alpha: 0.16) 透明度叠加在鸿蒙端能完美还原。从架构层面,宠物寄养应用要在鸿蒙端发挥价值,建议把核心能力划分为四层:底层是 ArkTS 写的"原生能力适配层",包含位置服务、推送、钱包、健康数据接入;中间层是 MethodChannel 桥;上层是 Dart 写的 UI 和业务逻辑层;最顶层是 FormExtensionAbility 写的桌面服务卡片。这四层的清晰分离让任意一层都可以独立替换。

开发核心代码

代码一:我的宠物(头像组+添加按钮)

宠物寄养页的灵魂是"我的毛孩子",必须放在 Header 之后最显眼的位置。我用 Row + 多个 CircleAvatar 表现头像组,最后一个圆位置放"+"添加按钮,让用户可以无缝继续录入新宠物。每只宠物用一个独立色相的 CircleAvatar,比统一同色更生动,呼应养宠人对每个毛孩子独立的情感投射。

Widget _myPets() {
  final pets = const [
    ['豆豆', _orange],
    ['咪咪', _pink],
    ['小灰', _cyan],
  ];
  return Container(
    padding: const EdgeInsets.all(14),
    decoration: BoxDecoration(color: _card,
        borderRadius: BorderRadius.circular(16)),
    child: Row(children: [
      const Text('我的宠物',
          style: TextStyle(color: _ink, fontSize: 14,
              fontWeight: FontWeight.w700)),
      const Spacer(),
      ...pets.map((p) => Padding(
        padding: const EdgeInsets.only(left: 8),
        child: Column(children: [
          CircleAvatar(radius: 22,
            backgroundColor: (p[1] as Color).withValues(alpha: 0.18),
            child: Icon(Icons.pets,
                color: p[1] as Color, size: 22),
          ),
          const SizedBox(height: 4),
          Text(p[0] as String, style: const TextStyle(
              color: _sub, fontSize: 11)),
        ]),
      )),
      const SizedBox(width: 8),
      Container(width: 44, height: 44,
        decoration: BoxDecoration(
          color: _orange.withValues(alpha: 0.14),
          borderRadius: BorderRadius.circular(22)),
        child: const Icon(Icons.add,
            color: _orange, size: 22),
      ),
    ]),
  );
}

宠物的真实头像在生产业务里来自用户上传或者宠物 ID 关联的服务端图片资源。建议把宠物档案数据存到鸿蒙的分布式数据对象里,这样用户在手机、平板、智慧屏上都能看到同一份档案,无需重复登录。分布式数据对象由 ArkTS 端 distributedDataObject API 维护,Flutter 这边通过 MethodChannel 同步获取或写入。

从布局编排和情绪化设计角度再补一段。这一组宠物头像采用「圆形头像 + 主题色浅背景 + 居中宠物图标」的占位形态,比起常见的灰色占位更有「家人感」——每只宠物用不同的主题色背景(橙、青、粉),在头像组里形成色彩斑斓的「家庭合影」效果,是养宠用户特别买账的视觉表达。末尾「+ 添加宠物」按钮做成虚线圆框 + 加号图标,故意区别于实心头像,让用户一眼识别出「这是入口不是已存在的宠物」——这种「内容用实心、操作用虚线」的视觉编码在表单类 UI 里非常通用。Row 内部用 SizedBox(width: 12) 控制头像间距,间距值刚好让两个相邻头像视觉上「亲密但不重叠」,是养宠类应用的黄金值。如果未来要支持长按拖拽调整宠物排序(比如把"主子"放到第一位),可以把每个头像包一层 LongPressDraggable,配合 DragTarget 做位置交换,鸿蒙 6.0 端的长按检测和拖拽性能与 Android 旗舰一致。
在这里插入图片描述

代码二:寄养家庭列表

寄养家庭卡片是预约的核心入口,必须包含:家庭名、地址、寄养类型(猫/狗/小型)、评分、起价、预约按钮。我用 Row + Column 把信息分两栏,“猫狗都收” chip 用浅色背景表达专业资质。

Widget _family(Map<String, String> f) {
  return Container(
    margin: const EdgeInsets.only(bottom: 10),
    padding: const EdgeInsets.all(14),
    decoration: BoxDecoration(color: _card,
        borderRadius: BorderRadius.circular(14)),
    child: Row(children: [
      Container(width: 56, height: 56,
        decoration: BoxDecoration(
          color: _orange.withValues(alpha: 0.14),
          borderRadius: BorderRadius.circular(14)),
        child: const Icon(Icons.house,
            color: _orange, size: 28),
      ),
      const SizedBox(width: 12),
      Expanded(child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(f['name']!, style: const TextStyle(
              color: _ink, fontSize: 14,
              fontWeight: FontWeight.w700)),
          const SizedBox(height: 4),
          Row(children: [
            const Icon(Icons.location_on, color: _sub, size: 12),
            Text(f['dist']!, style: const TextStyle(
                color: _sub, fontSize: 12)),
            const SizedBox(width: 8),
            Container(padding: const EdgeInsets.symmetric(
                horizontal: 6, vertical: 2),
              decoration: BoxDecoration(
                color: _cyan.withValues(alpha: 0.14),
                borderRadius: BorderRadius.circular(4)),
              child: Text(f['type']!,
                  style: const TextStyle(color: _cyan,
                      fontSize: 10, fontWeight: FontWeight.w700)),
            ),
          ]),
          const SizedBox(height: 6),
          Row(children: [
            const Icon(Icons.star, color: _amber, size: 14),
            Text(' ${f['score']}',
                style: const TextStyle(color: _amber,
                    fontSize: 12, fontWeight: FontWeight.w700)),
            const SizedBox(width: 8),
            Text('${f['orders']} 单',
                style: const TextStyle(
                    color: _sub, fontSize: 12)),
          ]),
        ],
      )),
      Column(crossAxisAlignment: CrossAxisAlignment.end, children: [
        Text('${f['price']}/天',
            style: const TextStyle(color: _orange, fontSize: 14,
                fontWeight: FontWeight.w800)),
        const SizedBox(height: 6),
        Container(padding: const EdgeInsets.symmetric(
            horizontal: 14, vertical: 6),
          decoration: BoxDecoration(color: _orange,
              borderRadius: BorderRadius.circular(20)),
          child: const Text('预约',
              style: TextStyle(color: Colors.white,
                  fontSize: 12, fontWeight: FontWeight.w700)),
        ),
      ]),
    ]),
  );
}

寄养家庭的真实场景里有非常多需要严格审核的资质——身份证认证、家庭环境照片、宠物经验证明、医疗合作等。这些信任元素的展示在 UI 上应该被强化,可以在卡片底部加"已认证 X 项"的小 chip 行。鸿蒙 6.0 在身份认证方面有原生 Verified Account 体系,开发者可以接入这套体系做"认证标识",比自己造轮子可信度高得多。

从信息密度与卡片布局美学角度再补一段。寄养家庭卡片把「头像 / 家庭名 + chip / 地址 / 评分 + 单数 / 起价 + 预约按钮」六段信息压在 14 像素内边距的卡片里,看起来信息密集但通过左中右三栏布局(头像 70 像素、信息区 Expanded、价格按钮 Column)保持了视觉清晰。这种三栏式排版在国内服务类 App 里被反复验证——左侧建立视觉锚点(头像)、中间承接核心识别信息(名字 + 资质 + 评分)、右侧承接转化路径(价格 + 按钮),是最高效的服务卡片范式。“猫狗都收” chip 用 12 号小字 + 主色浅背景,与右侧"预约"按钮(白字 + 主色实心)形成色彩分工——浅背景 chip 表达"资质标签不抢戏"、实心按钮表达"行动入口最显眼"。如果未来要在卡片上加入"已收藏"心形图标或"距您 1.2km"距离标识,可以放在标题右侧的 chip 后面,依旧不破坏整体节奏。

代码三:寄养中订单卡片

老用户回访时最关心"我家狗现在怎么样",所以页面底部放一个"寄养中"提醒卡片,包含宠物名、寄养家庭、剩余天数、查看详情按钮。渐变浅橙到浅粉的卡片背景非常符合宠物 App 的氛围调性。

Widget _onGoing() {
  return Container(
    padding: const EdgeInsets.all(16),
    decoration: BoxDecoration(
      gradient: LinearGradient(colors: [
        _orange.withValues(alpha: 0.14),
        _pink.withValues(alpha: 0.14),
      ]),
      borderRadius: BorderRadius.circular(14),
    ),
    child: Row(children: [
      Container(width: 50, height: 50,
        decoration: BoxDecoration(color: _orange,
            borderRadius: BorderRadius.circular(14)),
        child: const Icon(Icons.pets,
            color: Colors.white, size: 26),
      ),
      const SizedBox(width: 12),
      const Expanded(child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('豆豆寄养中 · 阳光温馨家',
              style: TextStyle(color: _ink, fontSize: 14,
                  fontWeight: FontWeight.w700)),
          SizedBox(height: 4),
          Text('已寄养 2 天 · 剩余 3 天',
              style: TextStyle(color: _sub, fontSize: 12)),
        ],
      )),
      Container(padding: const EdgeInsets.symmetric(
          horizontal: 12, vertical: 6),
        decoration: BoxDecoration(color: _orange,
            borderRadius: BorderRadius.circular(20)),
        child: const Text('查看',
            style: TextStyle(color: Colors.white,
                fontSize: 12, fontWeight: FontWeight.w700)),
      ),
    ]),
  );
}

"已寄养 2 天 · 剩余 3 天"这条进度信息可以做成桌面服务卡片放到鸿蒙桌面,让宠主长按桌面就能看到自家毛孩子的最新状态。如果要做得更高级,可以接入寄养家庭的摄像头流(通过鸿蒙超级终端 + 分布式相机能力),让用户点击"查看"后直接拉起一个分布式视频画面——这是鸿蒙端独有的体验,Android 上很难复刻。

从「订单状态卡」的视觉范式角度再补一段。寄养中订单卡用了「橙色渐变 Header + 大字号倒计时 + 副信息 + 行动按钮」的标准订单卡范式——这种范式在外卖、快递、打车、寄养这类「时间敏感」业务里几乎是通用模板,因为用户最关心的就是「还有多久结束 / 还剩多久到」。橙色渐变作为背景色比红色更克制——红色容易传递「警告」「危险」的负面情绪,橙色则传递「进行中」「温暖」的正面情绪,更适合宠物寄养这类亲情向场景。卡片右下角的"查看"白色按钮是常见的「白底 + 主题色文字」胶囊设计,与左上角的状态标签形成视觉对角线,让信息读取节奏自然流动。如果未来要在订单卡上叠加更多状态信息(比如喂食时间、健康打卡、视频片段),可以把当前 Column 的子项扩展,鸿蒙 6.0 的 Skia 对这种深色渐变卡片上的浅色叠加渲染极其稳定。
在这里插入图片描述

心得

宠物类 App 的视觉灵魂是"温暖且不卡通"——卡通会让人觉得不专业,太冷又会让用户对"安全"产生疑虑。色板上的橙 + 粉 + 青三色组合是经过反复验证的"温暖中带专业"的最佳组合。Material 自带的 Icons.pets 图标在鸿蒙 6.0 端渲染清晰锐利,无需引入任何自定义字体或 SVG。开发时一定要把"我的宠物"“寄养中"这些情感关联强的模块做大做亮,把"评价、列表、分类"这些理性模块做收敛——情感和理性的视觉权重比例大约是 6:4。从能力扩展看,宠物寄养应用最有想象力的鸿蒙端能力组合是"分布式相机 + 健康数据 + 桌面卡片”——分布式相机让宠主看到寄养画面、健康数据接入宠物可穿戴让数据可视、桌面卡片让一眼可见。把这些能力串起来,App 就从一个简单的"预约工具"进化成"宠物生活看板",用户粘性会有质的飞跃。

总结

本篇实现了 Harmony 6.0 端的宠物寄养预约首页,5 个模块、零依赖、约 360 行代码。骨架可直接迁移到宠物医疗、宠物美容、宠物用品等垂直场景。从扩展角度,建议生产业务里:把宠物档案接入分布式数据对象;把寄养家庭认证接入鸿蒙身份体系;把摄像头查看接入分布式相机能力;把"寄养中"做成 FormExtensionAbility 桌面卡片;把宠物健康数据接入 HealthKit。这些扩展都可以在不动当前 UI 骨架的前提下完成。下一篇是第三组最后一块——旅行行程规划应用。

在这里插入图片描述

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐