鸿蒙Next实战开发(一):项目初始化与四Tab底部导航架构建模

系列导读:本系列将带你从零到一完成一个完整的"智慧生活"鸿蒙原生App,涵盖Tabs导航、仪表盘、待办事项、备忘录、个人中心等核心模块。所有代码均基于 API 23(HarmonyOS 6.1.0),Stage模型 + ArkTS 开发。


一、写在前面

随着HarmonyOS Next的全面铺开,越来越多的开发者开始投入鸿蒙原生应用开发。然而,市面上的教程大多停留在单页Demo层面,真正涉及多页面、复杂交互的实战教程屈指可数。

本系列将以一个 “智慧生活” 应用为例,完整呈现一个复杂鸿蒙原生应用从0到1的开发过程。你可以学到:

  • Tabs底部导航架构设计
  • ArkTS组件化开发模式
  • 状态管理与数据流控制
  • 页面路由与参数传递
  • 手势交互与组件生命周期
  • 编译构建与真机调试

二、项目创建与环境准备

2.1 开发环境

打开 DevEco Studio,确保已安装 HarmonyOS SDK API 23(6.1.0.23)。

2.2 创建项目

点击 Create Project → 选择 Empty Ability 模板 → 配置如下:

  • Project Name: MyApplication
  • Bundle Name: com.example.myapplication
  • Save Location: D:\harmonyos\project\6.6\MyApplication
  • Compatible SDK: 6.1.0(23)
  • Device Type: Phone

2.3 项目目录结构

创建完成后,我们先看一下项目的初始结构:

MyApplication/
├── AppScope/                 # 应用级配置
│   └── app.json5             # 应用名称、版本、图标
├── entry/                    # 主模块
│   └── src/main/
│       ├── ets/
│       │   ├── entryability/ # Ability生命周期
│       │   └── pages/        # 页面文件
│       │       └── Index.ets # 默认首页
│       ├── module.json5      # 模块配置
│       └── resources/        # 资源文件
├── build-profile.json5       # 构建配置
└── hvigor/                   # 编译工具配置

关键配置项解读:

build-profile.json5 - 这是项目的核心构建配置:

{
  "app": {
    "products": [
      {
        "name": "default",
        "signingConfig": "default",
        "compatibleSdkVersion": "6.1.0(23)",  // API 23
        "runtimeOS": "HarmonyOS"
      }
    ]
  }
}

module.json5 - 模块入口配置,注册Ability和页面路由:

{
  "module": {
    "name": "entry",
    "type": "entry",
    "mainElement": "EntryAbility",
    "pages": "$profile:main_pages",
    "abilities": [
      {
        "name": "EntryAbility",
        "srcEntry": "./ets/entryability/EntryAbility.ets"
      }
    ]
  }
}

三、资源文件预配置

在开始写页面之前,我们先定义好应用的样式资源。鸿蒙的资源系统使用JSON格式,支持颜色(color)、字号(float)、字符串(string)等维度。

3.1 主题色定义

entry/src/main/resources/base/element/color.json

{
  "color": [
    { "name": "primary_color", "value": "#FF6B9CE3" },
    { "name": "primary_dark", "value": "#FF4A7BC7" },
    { "name": "background_color", "value": "#FFF5F7FA" },
    { "name": "card_background", "value": "#FFFFFFFF" },
    { "name": "text_primary", "value": "#FF1A1A2E" },
    { "name": "text_secondary", "value": "#FF6B7280" },
    { "name": "text_tertiary", "value": "#FF9CA3AF" },
    { "name": "divider_color", "value": "#FFE5E7EB" },
    { "name": "success_color", "value": "#FF10B981" },
    { "name": "warning_color", "value": "#FFF59E0B" },
    { "name": "danger_color", "value": "#FFEF4444" }
  ]
}

这里定义了一个以蓝色为主色调的配色方案,颜色命名遵循语义化原则,方便全局复用。

3.2 字号与间距定义

entry/src/main/resources/base/element/float.json

{
  "float": [
    { "name": "title_font_size", "value": "24fp" },
    { "name": "subtitle_font_size", "value": "18fp" },
    { "name": "body_font_size", "value": "16fp" },
    { "name": "caption_font_size", "value": "14fp" },
    { "name": "small_font_size", "value": "12fp" },
    { "name": "card_radius", "value": "16vp" },
    { "name": "button_radius", "value": "12vp" },
    { "name": "standard_padding", "value": "16vp" }
  ]
}

注意fp(Font Pixel)是鸿蒙特有的字体单位,兼顾屏幕适配和用户字体偏好设置。vp(Virtual Pixel)是虚拟像素单位,用于尺寸和间距。


四、Tabs底部导航架构设计

4.1 设计思路

底部Tab导航是移动应用最常见的导航模式。鸿蒙 ArkUI 提供了 Tabs + TabContent 组合来实现这一功能。

我们的"智慧生活"App规划了4个Tab页签:

图标 名称 功能
🏠 首页 仪表盘:天气、健康统计、快捷功能
待办 待办事项管理:增删改查、分类筛选
📝 备忘 备忘录:分类浏览、查看详情
👤 个人 个人中心:数据统计、功能入口

4.2 主页面框架

pages/Index.ets - 这是应用的入口页面,承载Tabs容器:

import { router } from '@kit.ArkUI';

// ==================== 主页面 ====================
@Entry
@Component
struct Index {
  @State currentIndex: number = 0;

  private tabBarItems: string[] = ['首页', '待办', '备忘', '个人'];
  private tabIcons: string[] = ['🏠', '✅', '📝', '👤'];

  build() {
    Column() {
      Tabs({ index: this.currentIndex }) {
        TabContent() {
          HomeContent();    // 首页组件
        }
        .tabBar(this.buildTabBar(0));

        TabContent() {
          TodoContent();    // 待办组件
        }
        .tabBar(this.buildTabBar(1));

        TabContent() {
          NotesContent();   // 备忘组件
        }
        .tabBar(this.buildTabBar(2));

        TabContent() {
          ProfileContent(); // 个人中心组件
        }
        .tabBar(this.buildTabBar(3));
      }
      .vertical(false)
      .scrollable(true)
      .barMode(BarMode.Fixed)
      .barWidth('100%')
      .barHeight(64)
      .backgroundColor($r('app.color.card_background'))
      .onChange((index: number) => {
        this.currentIndex = index;
      });
    }
    .width('100%')
    .height('100%')
    .backgroundColor($r('app.color.background_color'));
  }

  @Builder
  buildTabBar(index: number) {
    Column({ space: 2 }) {
      Text(this.tabIcons[index])
        .fontSize(22);
      Text(this.tabBarItems[index])
        .fontSize(10)
        .fontColor(this.currentIndex === index
          ? $r('app.color.primary_color')
          : $r('app.color.text_tertiary'));
      if (this.currentIndex === index) {
        Row()
          .width(20)
          .height(3)
          .backgroundColor($r('app.color.primary_color'))
          .borderRadius(2);
      }
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .padding({ top: 6 });
  }
}

代码要点解读:

  1. @Entry 装饰器:标识这是页面的入口组件,配合 main_pages.json 路由注册使用
  2. @Component 装饰器:声明这是一个可复用的自定义组件
  3. @State currentIndex:响应式状态变量,当Tab切换时自动驱动UI更新
  4. @Builder buildTabBar():构建函数,用于自定义TabBar的样式

4.3 Tabs组件核心属性

属性 作用
vertical false 水平方向排列
scrollable true 支持左右滑动切换
barMode BarMode.Fixed 固定宽度均分
barWidth '100%' 底部栏宽度铺满
barHeight 64 底部栏高度
onChange 回调 监听Tab切换事件

4.4 页面路由注册

entry/src/main/resources/base/profile/main_pages.json

{
  "src": [
    "pages/Index",
    "pages/NoteDetailPage",
    "pages/SettingsPage"
  ]
}

这里注册了3个页面路由。Index 是主页面,内部通过Tabs切换4个内容区;NoteDetailPageSettingsPage 是需要通过 router.pushUrl() 跳转的子页面。


五、组件化架构设计

5.1 为何选择组件化?

在单文件内定义多个组件,是鸿蒙 ArkTS 开发中的常见模式。每个Tab对应的业务模块独立成 @Component,好处有:

  • 职责分离:每个组件只关注自己的业务逻辑
  • 状态隔离@State 状态只在本组件内生效,不会相互污染
  • 可维护性:修改某个Tab不影响其他Tab

5.2 组件生命周期

ArkTS 组件有明确的生命周期钩子:

@Component
struct MyComponent {
  aboutToAppear(): void {
    // 组件即将创建时调用,适合做数据初始化
  }

  aboutToDisappear(): void {
    // 组件即将销毁时调用,适合做清理工作
  }

  build() {
    // 组件的UI描述,必须实现
  }
}

在我们的首页仪表盘组件中,就用 aboutToAppear 来生成当前日期:

@Component
struct HomeContent {
  @State todayDate: string = '';

  aboutToAppear(): void {
    const now = new Date();
    const weekDays = ['日', '一', '二', '三', '四', '五', '六'];
    this.todayDate = `${now.getFullYear()}${now.getMonth() + 1}${now.getDate()}日 星期${weekDays[now.getDay()]}`;
  }
}

六、数据类型定义

在多个组件之间共享的数据类型,我们定义为全局 interface

interface TodoItem {
  id: number;
  text: string;
  completed: boolean;
  priority: 'high' | 'medium' | 'low';
}

interface NoteItem {
  id: number;
  title: string;
  content: string;
  category: string;
  date: string;
}

这些接口定义在 Index.ets 文件顶部,在所有组件之前声明,确保全局可见。


七、本篇小结

本篇我们完成了:

  1. ✅ 开发环境配置与项目创建
  2. ✅ 资源文件预配置(颜色、字号)
  3. ✅ Tabs底部导航架构搭建
  4. ✅ 4个Tab对应的组件骨架
  5. ✅ 页面路由注册
  6. ✅ 数据类型定义

下一篇将进入 首页仪表盘待办事项模块 的完整开发,包含天气卡片、健康统计、待办增删改查等核心功能。
在这里插入图片描述


💡 配套资源:本文涉及的所有代码均已编译通过,可直接在模拟器上运行。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐