《2026鸿蒙NEXT纯血开发与AI辅助》第六章:「微距」项目启动——工程创建与整体架构设计-卓伊凡

简介: 《2026鸿蒙NEXT纯血开发与AI辅助》第六章启动「微距」项目:基于HarmonyOS 6.0 AR Engine的智能测量工具,支持单/多设备协同测量、端侧AI材质识别与安全数据管理,完成工程创建、模块化架构设计及Tab导航骨架搭建。

《2026鸿蒙NEXT纯血开发与AI辅助》第六章:「微距」项目启动——工程创建与整体架构设计-卓伊凡

从这一章开始,我们的专栏正式进入实战阶段。

前五章我们做了很多基础工作:下载 DevEco Studio、理解项目模板、熟悉 IDE 界面、跑通第一个 Hello World。这些不是浪费时间,而是在打地基。地基打好了,接下来盖楼的每一层才会稳。

这一章,我们要做的事情很明确:把「微距」这个项目真正创建出来,把整体架构设计清楚,把后续开发的路线图确定下来。

一、「微距」到底是个什么样的产品

在动手写代码之前,我们先把产品定义清楚。

很多开发者一上来就急着写代码,结果写到一半发现方向偏了,再回头调整成本巨大。所以这一节的每一个字,都请你认真看。

1.1 产品一句话定义

「微距」是一款基于 HarmonyOS 6.0 AR Engine 和 3D 空间化能力的智能测量工具,让用户的手机变成随身携带的多功能测量仪。

1.2 核心使用场景

我帮你梳理了四个最典型的使用场景,这些场景不是凭空想出来的,而是真实生活中经常遇到的:

场景一:家居量尺寸

你准备买一张新沙发,但不确定客厅能不能放得下。传统做法是翻箱倒柜找卷尺,然后一个人拉着尺子,另一个人帮忙看数据,折腾半天。用「微距」,打开应用,对准墙角,用手指在屏幕上点两个点,长度直接显示在 AR 画面上。如果是一个人操作,就更有用了,因为你不需要找人帮忙拉尺子。

场景二:搬家估体积

要搬家了,搬家公司问你大概有多少立方米的东西,你一懵。用「微距」,扫描几个大件家具,应用自动计算体积,还能把多个物体的体积累加起来,给你一个合理估算。这个场景是真实刚需,被搬家公司的报价单逼出来过的人都懂。

场景三:快递测量

你在闲鱼上卖了个东西,需要填快递运费。运费是按体积重和实重取大值算的,你得知道包裹的长宽高。用「微距」扫一下,长宽高和体积一目了然。

场景四:装修验房

装修完验房,墙面是不是平的?用「微距」的水平检测功能扫一下,哪里不平一目了然。这是专业功能,但用手机就能做,门槛降低了一百倍。

1.3 目标用户画像

维度

描述

年龄段

20-45 岁

城市分布

一二线城市为主,有租房、装修、网购需求的用户

行为特征

经常网购家具、喜欢 DIY 家居改造、关注智能工具

痛点

需要测量但手边没卷尺、一个人无法完成测量、需要估算体积

1.4 与竞品的差异化

市面上已经有 AR 测量类的应用,比如 iOS 的 Measure 应用,也有第三方测量 App。但它们有几个共同的问题:

  1. 单设备操作:只能用一台手机,不能两台设备协同测量大空间
  2. 无材质识别:只能测尺寸,不能告诉你被测物体的材质
  3. 数据不上云也不做本地加密:要么数据全上云有隐私风险,要么只存本地换手机就丢

而「微距」基于鸿蒙的能力,有三个核心差异化优势:

  1. 多设备协同测量:两个人各拿一台鸿蒙设备站在不同位置,数据自动拼接,测量更大更准
  2. 端侧 AI 材质识别:摄像头扫一下,自动识别木材、金属、玻璃等材质,离线可用,隐私安全
  3. 数据安全存储:测量数据端侧加密存储,不上云,通过鸿蒙分布式能力在多设备间安全同步

这三个点,也是后续参加创新赛时的核心得分点。

二、创建「微距」工程

产品定义清楚了,接下来就是正式创建工程。

2.1 选择哪个模板

我们在第五章详细对比过三种原生方案。对于「微距」这个项目,我们选择 Empty Ability

为什么不选 Native C++?因为 AR Engine 的 API 在 ArkTS 层已经有完整封装,我们不需要直接操作 C++ 层的 AR 接口。Empty Ability 够用,而且依赖关系最简洁,构建速度最快。

为什么不选 CloudDev Empty Ability?因为「微距」的核心功能都在端侧完成,不依赖云服务。数据存储也是本地为主,不需要云数据库。

所以,Empty Ability,干净利落。

2.2 工程配置

打开 DevEco Studio,点击 Create Project,选择 Empty Ability 模板,然后填写以下配置:

配置项

填写内容

说明

Project name

MicroDistance

项目名称,也就是「微距」的英文名

Bundle name

com.zhuoyifan.microdistance

应用包名,遵循反向域名规范

Save location

D:\Projects\MicroDistance

项目保存路径

Module name

entry

入口模块名,保持默认

Device type

Phone、Tablet

勾选手机和平板,因为「微距」需要在大屏上有更好的体验

Enable Native C++

不勾选

不涉及 C++ 开发

点击 Finish,等待工程初始化完成。

2.3 初始化验证

工程创建完成后,注意观察底部 Build 输出区。你应该看到的是 BUILD SUCCESSFUL,而不是第四章那种红色报错。

这里我强调一个习惯:每次创建新工程,第一件事永远是确认构建成功。 这是你的基线。如果构建失败,后面写的所有代码都是无效的。先排错,再开发。

三、项目的整体架构设计

工程跑通了,接下来是架构设计。

很多教程在这一步会直接开始写页面代码,但我们不这样做。因为「微距」不是一个演示 Demo,它是一个有完整功能模块的应用。如果不先把架构想清楚,写到后面一定会乱。

3.1 功能模块划分

我们把「微距」拆成五个核心功能模块:

┌─────────────────────────────────────────────┐
│                  「微距」应用                    │
├───────────┬───────────┬───────────┬──────────┤
│  AR测量   │  3D空间   │  协同测量  │  工具集   │
│  ┌─────┐  │  ┌─────┐  │  ┌─────┐  │  ┌─────┐  │
│  │ 长度 │  │  │空间建│  │  │设备发│  │  │水平仪│  │
│  │ 面积 │  │  │模    │  │  │现连接│  │  │高度计│  │
│  │ 体积 │  │  │3D标注│  │  │数据拼│  │  │材质识│  │
│  │ 角度 │  │  │      │  │  │接    │  │  │别   │  │
│  └─────┘  │  └─────┘  │  └─────┘  │  └─────┘  │
├───────────┴───────────┴───────────┴──────────┤
│                 数据管理层                      │
│           测量记录存储 / 历史管理 / 导出         │
└─────────────────────────────────────────────┘

这五个模块的职责分别是:

AR 测量:核心功能模块。包含长度测量、面积测量、体积测量、角度测量。用户通过摄像头对准真实世界,在屏幕上选点,实时计算并显示测量结果。

3D 空间:扫描真实空间,生成 3D 点云模型,可以在模型上标注尺寸。这个模块面向的是更专业的使用场景,比如装修前的空间规划。

协同测量:两台鸿蒙设备通过分布式能力连接,各自从不同角度测量,数据自动拼接。这个模块是「微距」区别于市面上所有其他测量 App 的核心竞争力。

工具集:包含水平仪、高度计、材质识别等辅助功能。这些是独立的小工具,和核心测量功能互补。

数据管理:所有测量记录的存储、历史查看、数据导出。测量完成不是结束,用户需要回看和分享。

3.2 页面导航结构

根据功能模块,我们设计应用的页面导航结构:

应用入口(Index.ets - 启动页)
主页面(MainPage.ets - TabBar 导航)
    ├── Tab 1:测量页(MeasurePage.ets)
    │   ├── 长度测量模式
    │   ├── 面积测量模式
    │   ├── 体积测量模式
    │   └── 角度测量模式
    ├── Tab 2:空间页(SpacePage.ets)
    │   ├── 3D 扫描入口
    │   ├── 历史模型列表
    │   └── 模型详情/标注
    ├── Tab 3:工具页(ToolsPage.ets)
    │   ├── 水平仪
    │   ├── 高度计
    │   └── 材质识别
    └── Tab 4:记录页(HistoryPage.ets)
        ├── 测量记录列表
        ├── 记录详情
        └── 数据导出

这是一个典型的底部四 Tab 导航结构。用户进入主页面后,通过底部的 Tab 栏切换四个核心功能区。

3.3 数据模型设计

在写任何 UI 代码之前,我们先把数据模型定义清楚。这是很多新手容易跳过的步骤,但没有数据模型,后面状态管理和数据持久化会很混乱。

测量记录模型(MeasRecord)

// 测量记录
class MeasRecord {
  id: string;                    // 唯一标识
  type: MeasType;                // 测量类型:长度/面积/体积/角度
  value: number;                 // 测量结果数值
  unit: string;                  // 单位:米/平方米/立方米/度
  points: Point3D[];             // 测量选点坐标列表
  material: string;              // 被测物体材质(AI识别结果)
  createTime: number;            // 创建时间戳
  location: Location;            // 测量时的地理位置
  imageUrl: string;              // 测量截图
  tags: string[];                // 用户自定义标签
}
// 测量类型枚举
enum MeasType {
  LENGTH = 'length',
  AREA = 'area',
  VOLUME = 'volume',
  ANGLE = 'angle'
}
// 3D 空间点
class Point3D {
  x: number;
  y: number;
  z: number;
}

3D 空间模型(SpaceModel)

// 3D 空间扫描结果
class SpaceModel {
  id: string;
  name: string;                  // 空间名称
  pointCloud: Point3D[];         // 点云数据
  annotations: Annotation[];     // 空间标注列表
  createTime: number;
  deviceModel: string;           // 扫描设备型号
}
// 空间标注
class Annotation {
  id: string;
  type: AnnotationType;          // 标注类型
  position: Point3D;             // 标注位置
  content: string;               // 标注内容
  measurement: MeasRecord;       // 关联的测量数据
}
enum AnnotationType {
  TEXT = 'text',                 // 文字标注
  DIMENSION = 'dimension',       // 尺寸标注
  MATERIAL = 'material'          // 材质标注
}

协同测量会话(CollabSession)

// 多设备协同测量会话
class CollabSession {
  sessionId: string;
  deviceList: DeviceInfo[];      // 参与设备列表
  measurements: MeasRecord[];    // 会话中的测量数据
  mergedData: MeasRecord[];      // 拼接后的数据
  status: SessionStatus;
}
class DeviceInfo {
  deviceId: string;
  deviceName: string;
  deviceType: string;
  position: Point3D;             // 设备相对位置
}
enum SessionStatus {
  CONNECTING = 'connecting',
  MEASURING = 'measuring',
  MERGING = 'merging',
  COMPLETED = 'completed'
}

3.4 技术选型与依赖

「微距」项目涉及的技术能力,以及对应使用的鸿蒙 SDK 和 API:

功能需求

使用的鸿蒙能力

API / SDK

AR 测量核心

AR Engine

@ohos/ar

3D 场景展示

ArkUI 3D 组件

@ohos/ui

摄像头调用

Camera Kit

@ohos/camera

多设备协同

分布式软总线

@ohos/distributed

材质识别

端侧 AI 视觉

@ohos/ai

传感器(水平仪)

Sensor Kit

@ohos/sensor

地理位置

Location Kit

@ohos/geoLocationManager

数据持久化

关系型数据库

@ohos/data.relationalStore

文件存储

文件管理

@ohos/file

这个表很重要。它明确了我们后面每个功能模块要用到什么能力,开发的时候按图索骥就行。

四、本章的代码实现:搭建页面导航骨架

架构设计完成了,接下来我们做第一个实际开发任务:把应用的页面导航骨架搭起来。

这一节的目标是:应用启动后,出现一个底部四个 Tab 的主页面,每个 Tab 对应一个功能模块的占位页面。

4.1 创建页面文件

首先,在 entry/src/main/ets/pages/ 目录下创建以下文件:

pages/
├── Index.ets           # 应用入口(自动生成,暂时保留不改)
├── MainPage.ets        # 主页面(TabBar 容器)
├── MeasurePage.ets     # 测量页
├── SpacePage.ets       # 空间页
├── ToolsPage.ets       # 工具页
└── HistoryPage.ets     # 记录页

4.2 实现 MainPage(TabBar 主页面)

MainPage.ets 是整个应用的核心容器,承载底部导航和四个页面的切换。

import MeasurePage from './MeasurePage';
import SpacePage from './SpacePage';
import ToolsPage from './ToolsPage';
import HistoryPage from './HistoryPage';
@Entry
@Component
struct MainPage {
  @State currentIndex: number = 0;
  // Tab 数据配置
  private tabItems: TabItem[] = [
    {
      title: '测量',
      icon: $r('app.media.ic_measure'),
      selectedIcon: $r('app.media.ic_measure_selected')
    },
    {
      title: '空间',
      icon: $r('app.media.ic_space'),
      selectedIcon: $r('app.media.ic_space_selected')
    },
    {
      title: '工具',
      icon: $r('app.media.ic_tools'),
      selectedIcon: $r('app.media.ic_tools_selected')
    },
    {
      title: '记录',
      icon: $r('app.media.ic_history'),
      selectedIcon: $r('app.media.ic_history_selected')
    }
  ];
  // 构建 TabBar 内容
  @Builder
  TabContentBuilder(index: number) {
    if (index === 0) {
      MeasurePage()
    } else if (index === 1) {
      SpacePage()
    } else if (index === 2) {
      ToolsPage()
    } else {
      HistoryPage()
    }
  }
  build() {
    Tabs({
      barPosition: BarPosition.End,
      index: this.currentIndex
    }) {
      ForEach(this.tabItems, (item: TabItem, tabIndex: number) => {
        TabContent() {
          this.TabContentBuilder(tabIndex)
        }
        .tabBar(this.TabBarBuilder(tabIndex))
      })
    }
    .onChange((index: number) => {
      this.currentIndex = index;
    })
    .barMode(BarMode.Fixed)
    .backgroundColor('#F5F5F5')
  }
  // Tab 栏样式构建器
  @Builder
  TabBarBuilder(index: number) {
    Column() {
      Image(this.currentIndex === index ?
        this.tabItems[index].selectedIcon :
        this.tabItems[index].icon)
        .width(24)
        .height(24)
        .objectFit(ImageFit.Contain)
      Text(this.tabItems[index].title)
        .fontSize(10)
        .fontColor(this.currentIndex === index ? '#007AFF' : '#999999')
        .margin({ top: 2 })
    }
    .padding({ top: 8, bottom: 8 })
    .width('100%')
    .alignItems(HorizontalAlign.Center)
    .onClick(() => {
      this.currentIndex = index;
    })
  }
}
// Tab 项数据接口
interface TabItem {
  title: string;
  icon: Resource;
  selectedIcon: Resource;
}

4.3 实现四个占位页面

四个功能页面目前先用最简单的占位代码,后续章节再逐一实现。

MeasurePage.ets(测量页)

@Component
export default struct MeasurePage {
  build() {
    Column() {
      // 顶部标题栏
      Row() {
        Text('AR 测量')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
      .padding({ left: 16, top: 48, right: 16, bottom: 16 })
      .backgroundColor('#FFFFFF')
      // 测量模式选择区域(占位)
      Column() {
        Text('测量模块即将上线')
          .fontSize(16)
          .fontColor('#999999')
      }
      .width('100%')
      .layoutWeight(1)
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%')
    .height('100%')
  }
}

SpacePage.ets(空间页)

@Component
export default struct SpacePage {
  build() {
    Column() {
      Row() {
        Text('3D 空间')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
      .padding({ left: 16, top: 48, right: 16, bottom: 16 })
      .backgroundColor('#FFFFFF')
      Column() {
        Text('3D 空间模块即将上线')
          .fontSize(16)
          .fontColor('#999999')
      }
      .width('100%')
      .layoutWeight(1)
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%')
    .height('100%')
  }
}

ToolsPage.ets(工具页)

@Component
export default struct ToolsPage {
  build() {
    Column() {
      Row() {
        Text('工具集')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
      .padding({ left: 16, top: 48, right: 16, bottom: 16 })
      .backgroundColor('#FFFFFF')
      Column() {
        Text('工具模块即将上线')
          .fontSize(16)
          .fontColor('#999999')
      }
      .width('100%')
      .layoutWeight(1)
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%')
    .height('100%')
  }
}

HistoryPage.ets(记录页)

@Component
export default struct HistoryPage {
  build() {
    Column() {
      Row() {
        Text('测量记录')
          .fontSize(20)
          .fontWeight(FontWeight.Bold)
      }
      .width('100%')
      .padding({ left: 16, top: 48, right: 16, bottom: 16 })
      .backgroundColor('#FFFFFF')
      Column() {
        Text('记录模块即将上线')
          .fontSize(16)
          .fontColor('#999999')
      }
      .width('100%')
      .layoutWeight(1)
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
    }
    .width('100%')
    .height('100%')
  }
}

4.4 修改应用入口

找到 entry/src/main/ets/entryability/EntryAbility.ets,确认 onWindowStageCreate 中加载的是 MainPage

import { UIAbility } from '@kit.AbilityKit';
import { window } from '@kit.ArkUI';
import { hilog } from '@kit.PerformanceAnalysisKit';
export default class EntryAbility extends UIAbility {
  onWindowStageCreate(windowStage: window.WindowStage): void {
    // 应用启动时加载主页面
    windowStage.loadContent('pages/MainPage', (err, data) => {
      if (err.code) {
        hilog.error(0x0000, 'microdistance', 'Failed to load content. Cause: %{public}s', JSON.stringify(err) ?? '');
        return;
      }
      hilog.info(0x0000, 'microdistance', 'Succeeded in loading content. Data: %{public}s', JSON.stringify(data) ?? '');
    });
  }
}

4.5 添加 Tab 图标资源

entry/src/main/resources/base/media/ 目录下,需要准备以下图标文件:

media/
├── ic_measure.png            # 测量 Tab 默认图标
├── ic_measure_selected.png   # 测量 Tab 选中图标
├── ic_space.png              # 空间 Tab 默认图标
├── ic_space_selected.png     # 空间 Tab 选中图标
├── ic_tools.png              # 工具 Tab 默认图标
├── ic_tools_selected.png     # 工具 Tab 选中图标
├── ic_history.png            # 记录 Tab 默认图标
├── ic_history_selected.png   # 记录 Tab 选中图标

在正式的开发中,你需要自己制作或从图标库中导出这些图标。作为教学演示,你可以先用简单的纯色方块替代,确保功能跑通后再替换为正式图标。

五、运行验证

代码写完了,我们验证一下。

启动本地真机模拟器,点击 Run,你应该看到:

  1. 应用启动后直接进入主页面
  2. 底部有四个 Tab:测量、空间、工具、记录
  3. 点击不同的 Tab,页面会切换,每个页面显示各自的标题和"即将上线"占位文字
  4. 选中的 Tab 图标和文字颜色会高亮

如果这四步都能正常运作,说明你的页面导航骨架已经搭建成功。

目录
相关文章
|
3天前
|
人工智能 JSON 供应链
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
LucianaiB分享零成本畅用JVS Claw教程(学生认证享7个月使用权),并开源GeoMind项目——将JVS改造为科研与产业地理情报可视化AI助手,支持飞书文档解析、地理编码与腾讯地图可视化,助力产业关系图谱构建。
23283 2
畅用7个月无影 JVS Claw |手把手教你把JVS改造成「科研与产业地理情报可视化大师」
|
4天前
|
人工智能 API 开发工具
Claude Code国内安装:2026最新保姆教程(附cc-switch配置)
Claude Code是我目前最推荐的AI编程工具,没有之一。 它可能不是最简单的,但绝对是上限最高的。一旦跑通安装、接上模型、定好规范,你会发现很多原本需要几小时的工作,现在几分钟就能搞定。 这套方案的核心优势就三个字:可控性。你不用依赖任何不稳定服务,所有组件都在自己手里。模型效果不好?换一个。框架更新了?自己决定升不升。 这才是AI时代开发者该有的姿势——不是被动等喂饭,而是主动搭建自己的生产力基础设施。 希望这篇保姆教程,能帮你顺利上车。做出你自己的作品。
7375 18
Claude Code国内安装:2026最新保姆教程(附cc-switch配置)
|
12天前
|
缓存 人工智能 自然语言处理
我对比了8个Claude API中转站,踩了不少坑,总结给你
本文是个人开发者耗时1周实测的8大Claude中转平台横向评测,聚焦Claude Code真实体验:以加权均价(¥/M token)、内部汇率、缓存支持、模型真实性及稳定性为核心指标。
4565 24
|
8天前
|
人工智能 JSON BI
DeepSeek V4 来了!超越 Claude Sonnet 4.5,赶紧对接 Claude Code 体验一把
JeecgBoot AI专题研究 把 Claude Code 接入 DeepSeek V4Pro 的真实体验与避坑记录 本文记录我将 Claude Code 对接 DeepSeek 最新模型(V4Pro)后的真实体验,测试了 Skills 自动化查询和积木报表 AI 建表两个场景——有惊喜,也踩
3207 11
|
6天前
|
人工智能 缓存 BI
Claude Code + DeepSeek V4-Pro 真实评测:除了贵,没别的毛病
JeecgBoot AI专题研究 把 Claude Code 接入 DeepSeek V4Pro,跑完 Skills —— OA 审批、大屏、报表、部署 5 大实战场景后的真实体验 ![](https://oscimg.oschina.net/oscnet/up608d34aeb6bafc47f
2626 8
Claude Code + DeepSeek V4-Pro 真实评测:除了贵,没别的毛病
|
24天前
|
人工智能 自然语言处理 安全
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)
本文介绍了Claude Code终端AI助手的使用指南,主要内容包括:1)常用命令如版本查看、项目启动和更新;2)三种工作模式切换及界面说明;3)核心功能指令速查表,包含初始化、压缩对话、清除历史等操作;4)详细解析了/init、/help、/clear、/compact、/memory等关键命令的使用场景和语法。文章通过丰富的界面截图和场景示例,帮助开发者快速掌握如何通过命令行和交互界面高效使用Claude Code进行项目开发,特别强调了CLAUDE.md文件作为项目知识库的核心作用。
20214 61
Claude Code 全攻略:命令大全 + 实战工作流(建议收藏)