首页布局重构——从课程列表到英语学习首页

在这里插入图片描述

一、首页的定位与模块概览

首页是用户打开应用后看到的第一个界面。在英语学习 App 中,首页需要同时满足"快速开始学习"和"了解学习进展"两个核心诉求。

本项目的首页 MainPage.ets 位于 features/homePage/src/main/ets/pages/MainPage.ets,由 6 个 Builder 模块组成:

MainPage (Column)
 ├── topBarBuilder()        → 顶部搜索栏
 ├── todayStudyBuilder()    → 今日学习卡
 ├── swiperBuilder()        → 轮播图
 ├── functionBarBuilder()   → 5 宫格功能入口
 ├── practiceModeBuilder()  → 2x2 练习模式
 └── subjectPracticeBuilder() → 学习进度区

二、模块详细分析

2.1 顶部搜索栏(topBarBuilder)

@Builder
topBarBuilder() {
  Row() {
    // Logo 或标题
    Text('英语学习')
      .fontSize(22)
      .fontWeight(FontWeight.Bold);
    Blank();
    // 搜索图标
    Image($r('app.media.ic_search'))
      .width(24)
      .height(24);
    // 消息图标
    Image($r('app.media.ic_mic'))
      .width(24)
      .height(24);
  }
  .width('100%')
  .padding({ top: 12, bottom: 8 });
}

搜索栏布局为 “标题 + Blank + 图标” 的左中右结构。Blank() 组件自动填充中间空白区域,将图标推到右侧。

2.2 今日学习卡(todayStudyBuilder)

今日学习卡展示用户当日的学习进展,是本页最核心的信息模块:

@Builder
todayStudyBuilder() {
  Column() {
    Row() {
      Column() {
        Text('今日学习')
          .fontSize(16)
          .fontWeight(FontWeight.Bold);
        Text('坚持学习,成为更好的自己')
          .fontSize(12)
          .fontColor(Color.Gray);
      }
      .alignItems(HorizontalAlign.Start);

      Blank();

      // 学习进度圆环
      Progress({ value: 65, total: 100, type: ProgressType.Ring })
        .width(50)
        .height(50)
        .color('#165DFF')
        .style({ strokeWidth: 4 });
    }
    .width('100%');

    // 今日目标进度条
    Progress({ value: 13, total: 30, type: ProgressType.Linear })
      .width('100%')
      .height(6)
      .color('#165DFF');
    Text('今日已学 13/30 词')
      .fontSize(11)
      .fontColor(Color.Gray);
  }
  .padding(16)
  .borderRadius(16)
  .backgroundColor(Color.White);
}

学习卡使用 Progress 组件来可视化目标完成度,环形进度展示总体完成率,线性进度条显示具体的单词学习进度。

2.3 轮播图(swiperBuilder)

使用 ArkUI 的 Swiper 组件实现广告或功能推荐轮播:

@Builder
swiperBuilder() {
  Swiper() {
    ForEach(this.bannerList, (item: BannerItem) => {
      Image(item.image)
        .width('100%')
        .aspectRatio(2.2)
        .borderRadius(12);
    });
  }
  .autoPlay(true)
  .interval(3000)
  .indicator(true)
  .loop(true);
}

Swiper 通过 autoPlay 开启自动轮播,interval 设置 3 秒切换间隔,indicator 显示底部导航点。

2.4 5 宫格功能入口(functionBarBuilder)

将核心功能以网格形式展示,每个入口由图标 + 文字组成:

@Local functions: CourseCoreBar[] = [
  new CourseCoreBar($r('app.media.ic_practice_camera'), '搜单词'),
  new CourseCoreBar($r('app.media.ic__practice_wrong_question'), '易错词'),
  new CourseCoreBar($r('app.media.ic_practice_star'), '生词本'),
  new CourseCoreBar($r('app.media.ic_practice_notes'), '笔记'),
  new CourseCoreBar($r('app.media.ic_chart_report'), '学习报告')
];

@Builder
functionBarBuilder() {
  Grid() {
    ForEach(this.functions, (item: CourseCoreBar) => {
      GridItem() {
        Column() {
          Image(item.icon).width(32).height(32);
          Text(item.label).fontSize(12).margin({ top: 4 });
        }
      }
    });
  }
  .columnsTemplate('1fr 1fr 1fr 1fr 1fr')
  .rowsTemplate('1fr')
  .columnsGap(8);
}

columnsTemplate('1fr 1fr 1fr 1fr 1fr') 将 Grid 分为 5 等份,每个 GridItem 占据一格,形成经典的 5 宫格布局。

2.5 2x2 练习模式(practiceModeBuilder)

用 Grid 的 2 行 2 列展示练习模式入口,比 5 宫格更开阔:

@Builder
practiceModeBuilder() {
  Grid() {
    ForEach(this.practiceModes, (item: PracticeMode) => {
      GridItem() {
        Column() {
          Text(item.title).fontSize(16).fontWeight(FontWeight.Bold);
          Text(item.desc).fontSize(12).fontColor(Color.Gray);
        }
        .padding(20)
        .borderRadius(16)
        .backgroundColor(item.color);
      }
    });
  }
  .columnsTemplate('1fr 1fr')
  .rowsTemplate('1fr 1fr')
  .rowsGap(12)
  .columnsGap(12);
}

每个 GridItem 是一张带有背景色的卡片,展示 CET-4 核心词汇、听力训练、阅读理解、语法练习四个入口。

2.6 学习进度区(subjectPracticeBuilder)

展示按学科分类的详细学习进度:

@Local coursePractice: CourseQuestions[] = [
  new CourseQuestions('CET-4 核心词汇', 120, 300, 85, '2025-01-15 14:30'),
  new CourseQuestions('CET-6 高频词汇', 1024, 3411, 85, '2025-01-15 14:30'),
  // ...
];

每项展示已学题数/总题数、正确率、最后学习时间。

三、整体布局分析

build() {
  Column() {
    Flex({ direction: FlexDirection.Column }) {
      this.topBarBuilder();
      Scroll() {
        Column({ space: 10 }) {
          this.todayStudyBuilder();
          this.swiperBuilder();
          this.functionBarBuilder();
          this.practiceModeBuilder();
          this.subjectPracticeBuilder();
          Blank().layoutWeight(1);
        }
      }
      .scrollBar(BarState.Off)
      .layoutWeight(1);
    };
  }
  .padding({ left: 16, right: 16 })
  .backgroundColor($r('sys.color.background_secondary'))
  .width('100%')
  .height('100%');
}

布局要点:

  • 顶部搜索栏固定在顶部,不随滚动移动
  • 内容区域用 Scroll 包裹,处理内容超长时的滚动
  • layoutWeight(1) 让 Scroll 填充剩余高度
  • 统一使用 space: 10 控制模块间距
  • 整体使用 Flex 垂直布局,固定顶部 + 滚动区域

四、与课程列表首页的区别

从"课程列表"到"英语学习首页"的本质变化:

对比维度课程列表首页英语学习首页
核心目标浏览课程快速学习 + 查看进展
布局结构列表 (List)卡片组合 (Card + Grid)
数据展示课程名称、价格学习进度、功能入口
用户状态浏览者学习者(有学习历史)
交互重心点击进入详情直接开始学习

首页不再是"商店货架"式的课程陈列,而是围绕"今日学习"展开的进度中心。每个模块都在引导用户进入学习状态,这是英语学习 App 与教育 App 在设计理念上的关键区别。

五、总结

MainPage 的 6 个 Builder 模块展示了 ArkTS 强大的组件化能力。通过 @Builder 装饰器将首页拆分为独立模块,每个模块聚焦一个功能点,既便于阅读和维护,也为后续的个性化配置(如用户自定义首页模块的排序)奠定了基础。

Logo

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

更多推荐