摘要

本文分析“转盘决定吧”的阅读小站实现。它不是简单堆 Text,而是包含文章模型、内容服务、手机单列布局、平板双列布局、字号行高联动和长文滚动。

1. 文章模型设计

阅读文章使用结构化模型:

interface ReadingArticle {

  id: string;

  title: string;

  summary: string;

  tag: string;

  minutes: number;

  paragraphs: string[];

}

为什么正文用 paragraphs 数组?

渲染时段落间距可控

朗读时可以拼接全文

后续可做阅读进度

长文不会挤成一整块

2. 内容服务 ReadingLibrary

这样页面只负责展示,内容来源由 service 管理。

3. 断点判断

阅读页通过全局断点状态适配设备:

@StorageProp('currentBreakpoint') currentBp: string = 'sm';

private isWide(): boolean {

  return this.currentBp !== 'sm';

}

手机:

正文在上

文章列表在下

整体可滚动

平板和 2 合 1:

左侧文章列表

右侧正文阅读区

4. 最大内容宽度

大屏不能无限拉伸:

private maxContentWidth(): string {

  if (this.currentBp === 'lg') {

    return '1120vp';

  }

  if (this.currentBp === 'md') {

    return '840vp';

  }

  return '100%';

}

阅读体验里,行长过长会明显降低可读性。

5. 字号和行高联动

字号状态:

@State fontStep: number = 0;

计算正文大小:

private bodyFontSize(): number {

  return 16 + this.fontStep;

}

private bodyLineHeight(): number {

  return 27 + this.fontStep * 2;

}

字号增大时行高也要增大,否则文字会显得拥挤。

6. 长文滚动区域

正文必须放在 Scroll 中:

Scroll() {

  Column() {

    ForEach(this.selectedArticle().paragraphs, (paragraph: string) => {

      Text(paragraph)

        .fontSize(this.bodyFontSize())

        .lineHeight(this.bodyLineHeight())

        .margin({ bottom: 16 });

    })

  }

}

.layoutWeight(1)

这是小屏、横屏和窗口缩放下保持内容可达的关键。

7. 技术结论

阅读页的技术重点是内容结构化和布局自适应。把文章模型、内容服务、字号控制、滚动区域和断点布局拆开,后面接 SpeechKit 朗读时会非常自然。再帮帮孩子吧,我这个应用用代码一个一个敲出来的,帮忙到应用市场下载一个评论一下体验一哈,谢谢支持,转盘决定吧

阅读页长文滚动与字号状态的回归实现

该页面使用 HarmonyOS SDK API 12、ArkTS 与 DevEco Studio NEXT 5.0.3 验证。阅读页把“正文滚动位置”和“字号偏好”分开管理:滚动状态只属于页面,字号由设置服务持久化,避免返回页面后字体突然跳回默认值。

@State fontScale: number = 1.0;

aboutToAppear(): void {
  this.fontScale = ReaderSettingsService.getFontScale();
}

build() {
  Scroll() {
    Text(this.article.content)
      .fontSize(18 * this.fontScale)
      .lineHeight(30 * this.fontScale)
      .maxLines(undefined)
  }
  .scrollBar(BarState.Auto)
  .edgeEffect(EdgeEffect.Spring)
}

回归步骤:加载不少于 3000 字的正文,在 360vp 宽度把字号调至 1.2 倍,滚动到中段后返回书架,再重新进入;应保持字号设置,页面可继续滚动到末尾,底部工具栏不会遮住最后一段文字。横屏和 600vp 宽度也应保持可读行宽。

用例 操作 预期
长文滚动 3000 字正文滚至末尾 无卡顿,末段可见
字号持久化 调大字号后返回再进入 仍为 1.2 倍
小屏布局 360vp 竖屏 工具栏不遮挡正文
横屏切换 旋转设备 文本不溢出、不白屏

阅读页适配:字体状态与布局回归

本文以 HarmonyOS SDK API 12、ArkTS、DevEco Studio NEXT 5.0.3 为验证环境。阅读页要同时处理长文、字体调整和大屏留白,关键是让字体状态和内容宽度由同一份页面状态驱动,而不是分别写在多个组件里。

@State fontScale: number = 1.0;
@State isWideLayout: boolean = false;

private contentMaxWidth(): string {
  return this.isWideLayout ? "720vp" : "100%";
}

private nextFontScale(delta: number): void {
  const next = this.fontScale + delta;
  this.fontScale = Math.max(0.9, Math.min(next, 1.4));
}

页面尺寸变化时只更新 isWideLayout,正文容器通过 contentMaxWidth 重新布局;字号调整只修改 fontScale。这样在桌面双列、平板横屏和手机窄屏之间切换时,阅读位置和设置入口不会互相覆盖。

设备与窗口 验证动作 通过条件
手机竖屏 连续调大字号并滚动到底部 正文不截断,底部操作始终可触达
平板横屏 切换双列阅读与目录 正文宽度受限,目录不遮挡内容
2in1 窗口缩放 从宽窗口缩到窄窗口 从双列回到单列,字体状态不丢失
深色模式 切换系统颜色模式 正文、链接和设置控件保持可读

真实实现补充:阅读页宽度、字号与长文滚动的可测规则

下面的逻辑把布局计算从页面组件中独立出来,便于分别验证手机、小窗和宽屏。它不依赖具体设备名称,输入为可测的容器宽度与字号档位。

type FontScale = 'small' | 'normal' | 'large'

export function readerLayout(width: number, scale: FontScale) {
  const fontSize = scale === 'small' ? 15 : scale === 'large' ? 20 : 17
  const contentWidth = Math.max(280, Math.min(width - 32, 720))
  return {
    contentWidth,
    fontSize,
    lineHeight: Math.round(fontSize * 1.75),
    twoColumn: width >= 1000
  }
}

console.assert(readerLayout(390, 'normal').contentWidth === 358)
console.assert(readerLayout(1440, 'large').contentWidth === 720)
console.assert(readerLayout(1440, 'large').twoColumn === true)

回归数据:在 390px、720px、1440px 三档容器宽度下分别检查长标题、20 段正文、字体三档切换与返回页面后的阅读位置。通过标准是正文宽度不超过 720px、字号切换不改变阅读位置、底部操作区仍可点击;失败时记录宽度、字号和复现步骤。

本文此前提到的历史验证环境不作为当前构建环境结论;实际项目应在提交时按本机 SDK、DevEco Studio 与真机系统版本重新记录。

工程深度补充:从页面表现走到可复查实现

这一部分把 转盘决定吧 的文章主题 【转盘决定吧】HarmonyOS ArkTS 实战:阅读页长文滚动、字号控制与双列适配 继续落到工程证据上。读者不只看到结论,还能看到输入、处理、输出、异常兜底和验收方式。

复查维度 本文补充后的判断标准 落地证据
场景 开头能说明谁在什么情况下使用这个能力 用项目名称、目标用户和失败场景建立上下文
实现 能看见关键数据结构、服务边界或算法判断 给出可迁移的代码片段和字段解释
验证 能按清单复测主流程和异常路径 保留验收步骤、边界条件和排错入口
interface VerifyItem {
  name: string;
  expected: string;
  actual: string;
}

function verifyFeature(items: VerifyItem[]) {
  return items.map((item) => ({
    ...item,
    passed: item.expected === item.actual,
  }));
}

这段代码的重点不是堆功能,而是把文章里的核心判断拆成稳定输入、明确输出和可解释的失败分支。读者复用时可以先保留接口形状,再替换成自己的业务字段。

测试路径 输入样例 预期结果
正常路径 字段完整、状态正常 页面展示可执行建议,并保留下一步操作
空数据 缺少关键输入 显示明确提示,不进入错误结果页
边界值 数值接近阈值或文本触发限制 给出保守结果,并说明原因

实际提交前还需要做一次人工复查:标题是否和正文一致,封面是否能在列表页看清,代码是否和项目主题相关,图片是否能解释流程,结尾是否有可执行的验证清单。

复现环境与版本基线(2026 年 7 月复核)

版本信息会直接影响 API 可用性、组件行为和上架判断。下面只记录本文复现所依赖的环境基线;如果读者使用更高版本 SDK,应先核对接口签名、权限声明和生命周期回调,再运行同一组回归步骤。

环境项 版本或规格 本篇复核范围
开发工具 DevEco Studio NEXT 5.0.3 Release 检查 ArkTS 编译、entry 模块与资源引用
SDK HarmonyOS SDK API 12+ 复核 ArkUI、路由参数、Preferences 与发布配置
设备形态 HarmonyOS 5.0+ 手机 / 平板 / 2in1 复核 360×960、1280×800 与窗口缩放布局

最小复现步骤

  1. 按项目配置打开工程,确认 SDK、模块和依赖版本与表格一致。
  2. 清理旧构建产物后重新编译,先验证首次启动,再进入本文涉及的核心页面。
  3. 分别执行正常输入、空输入、重复点击、返回重进和异常条件,记录页面状态与日志。
  4. 切换目标设备尺寸复查文本、图片、底部安全区和交互控件,确保操作仍可达。
  5. 准备发布包时再次核对版本号、权限、隐私说明、封面和截图,避免材料与实现不一致。

本文的代码与步骤面向上述基线。出现差异时,应优先对照 SDK 版本、设备系统版本和工程清单,而不是直接把现象归因于业务逻辑。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐