前言

富文本展示在应用里很常见。新闻详情、商品说明、活动规则、隐私协议,这些页面往往都带有排版、图片和层级标题。RichText 适合处理这类场景,它负责把 HTML 内容解析出来并渲染到界面上。到了 API 20,这个组件多了一个很实用的能力,content 不再只接字符串,也可以直接接本地资源,这样就能把 HTML 文件和图片资源一起打包进应用,直接走离线渲染。

这项能力落到工程里,最直接的好处有三个。第一,静态内容不需要再走网络。第二,图片和文案可以跟版本一起发布,资源管理会更统一。第三,协议页、帮助页、活动说明这类内容可以彻底脱离接口依赖,在弱网和离线状态下也能正常显示。HarmonyOS 的 rawfile 资源本身就放在 resources/rawfile 目录下,适合承接这类静态文件。

一、RichText 升级的核心

RichText 的定位很清楚,就是把一段 HTML 内容展示出来。API 20 这次有价值的点,集中在本地资源引用能力。内容来源一旦能直接走 Resource,很多原来必须靠接口下发或者硬编码字符串处理的页面,就可以改成直接读取本地 HTML 文件。对于协议、帮助中心、说明文档这类内容稳定、样式简单的页面,这个变化非常实用。

工程里最常见的旧写法有两种。一种是把 HTML 整段写在代码里,页面一长,组件代码会越来越难看。另一种是从网络拿 HTML,再把图片地址跟着一起下发。前者维护成本高,后者对网络依赖重。把 HTML 文件、图片和图标一起放进 rawfile 目录之后,这两类问题都会收很多。rawfile 目录本来就是给原始资源文件准备的,本地 HTML、图片、JSON、模板文件都适合放这里。

如果页面只是单纯展示内容,RichText 依然够用。页面一旦需要更复杂的交互、更深的样式控制或者脚本能力,再去考虑 Web 或 RichEditor 会更合适。这个取舍最好一开始就想清楚,后面重构成本会低很多。

二、本地HTML和图片怎么组织

这类页面接起来并不复杂,先把资源目录理顺就行。最常见的做法,是在 src/main/resources/rawfile 下放一个 HTML 文件,再配一个 images 子目录存放图片。HTML 内容里如果要引用本地图片,路径直接写成 resource://rawfile/相对路径。页面代码这边再用 $rawfile('文件名') 把 HTML 文件引进来。这样一套下来,HTML 和图片就串起来了。

一个比较稳的目录结构可以写成这样:

src/main/resources/rawfile/
├── privacy.html
└── images/
    ├── info_collection.png
    ├── info_usage.png
    └── info_sharing.png

HTML 文件里,图片路径按 rawfile 目录来写就行:

<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width">
  <style>
    h1 { color: #333; text-align: center; }
    h2 { color: #666; margin-top: 20px; }
    p { line-height: 1.6; color: #444; }
    .highlight { background-color: #f5f5f5; padding: 10px; }
  </style>
</head>
<body>
  <h1>用户隐私协议</h1>
  <div class="highlight">
    <p>最近更新日期:2026年1月1日</p>
  </div>

  <h2>一、信息收集</h2>
  <p>我们会收集您主动提供的信息,以及您在使用服务过程中产生的必要数据。</p>
  <image src="resource://rawfile/images/info_collection.png"></image>

  <h2>二、信息使用</h2>
  <p>这些信息用于提供服务、优化体验和提升账户安全性。</p>
  <image src="resource://rawfile/images/info_usage.png"></image>
</body>
</html>

这里有两个点最好记住。第一,HTML 文件本身放在 rawfile,图片也放在 rawfile 的相对目录里。第二,图片路径不要写成页面文件系统路径,直接走 resource://rawfile/ 这套协议最稳。这样资源会跟着应用一起打包,分发和更新路径也会更统一。

三、页面、滚动和加载状态的处理

页面侧的接法很直接,核心就是一句 RichText($rawfile('privacy.html'))。如果内容比较短,这样接就够了。实际项目里,协议页、帮助页通常比较长,这时候最好把它放进 Scroll 里,再把加载状态和日志一起补上,后面排查图片没显示、页面没刷新这类问题会更容易。

import hilog from '@ohos.hilog';

@Entry
@Component
struct PrivacyPolicyPage {
  build() {
    Scroll() {
      Column() {
        RichText($rawfile('privacy.html'))
          .width('100%')
          .height(1200)
          .onStart(() => {
            hilog.info(0x0000, 'PrivacyPolicy', 'HTML 开始加载');
          })
          .onComplete(() => {
            hilog.info(0x0000, 'PrivacyPolicy', 'HTML 加载完成');
          })
      }
      .width('100%')
      .padding(16)
    }
    .width('100%')
    .height('100%')
    .scrollBar(BarState.Auto)
  }
}

这段代码里最需要注意的是高度。RichText 这类组件在实际使用时,最好别完全依赖默认布局行为,尤其在滚动页面里,显示区域要尽量提前定清楚。内容短一点可以给固定高度,内容多的时候可以按页面类型拆出不同模板,别把所有富文本页都塞进同一套死板布局里。

如果页面里要根据不同主题切换不同 HTML 文件,也可以单独做一层资源映射。这样帮助中心、协议页、活动规则页都能走同一套渲染逻辑,后面维护会轻很多。

class HelpDocManager {
  private docMap: Record<string, string> = {
    'getting-started': 'help/getting_started.html',
    'account': 'help/account.html',
    'payment': 'help/payment.html',
    'privacy': 'privacy.html'
  };

  getDocument(topic: string): Resource {
    const fileName = this.docMap[topic] || 'help/default.html';
    return $rawfile(fileName);
  }
}

const helpManager = new HelpDocManager();

@Entry
@Component
struct HelpPage {
  @State topic: string = 'getting-started';

  build() {
    Column() {
      RichText(helpManager.getDocument(this.topic))
        .width('100%')
        .height('100%')
    }
  }
}

这种写法很适合内容比较多的项目,文档和页面渲染分开,后面版本迭代也会顺很多。

四、开发里最容易踩的坑

这类页面最容易踩的坑有三个。

第一个是图片不显示。这个问题排查顺序很简单,先看 HTML 有没有正常渲染,再看图片路径是不是写成了 resource://rawfile/...,最后再看图片文件是不是确实放在了 rawfile 对应目录里。大多数情况下,问题都出在路径没对齐。

第二个是页面布局跑偏。富文本里如果样式写得太随意,到了移动端很容易溢出或者出现滚动异常。最稳的做法,是在 HTML 头部把 viewport 补上,样式尽量控制在基础范围内,别把网页端那套特别复杂的布局直接搬过来。协议页、帮助页、本地说明页这类内容,本身就不需要太多花哨效果,简洁反而更稳。

第三个是性能。RichText 本质上更适合静态展示,不适合在长列表里反复创建。列表项一多,滚动场景里反复挂 RichText,页面很容易卡。遇到这种场景,更实际的做法是提前把内容结构化,简单文本直接拆成 Text 和 Span,复杂页面再评估是否改成 Web。这样做,性能和维护成本都会更容易控制。

项目里如果有很多富文本页,建议把这几条规则先定下来。静态内容走 rawfile,本地图片统一走 resource://rawfile/,页面层统一接 RichText($rawfile(...)),协议和帮助页走同一套资源映射逻辑,滚动容器里不要重复堆 RichText。规则先定清楚,后面团队协作会轻很多。

总结

RichText 在 API 20 这次升级里,真正有价值的点,就是把本地资源引用这条路补完整了。HTML 可以直接走 Resource,图片可以通过 resource://rawfile/ 引进来,协议页、帮助页、活动说明页这类静态内容终于可以彻底摆脱网络依赖。

Logo

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

更多推荐