HarmonyOS鸿蒙Next 6强调的“一次开发”理念,如何指导应用的主题色和字体大小的跨端自适应?

HarmonyOS鸿蒙Next 6强调的“一次开发”理念,如何指导应用的主题色和字体大小的跨端自适应? 多端部署中,应用的主题色和字体大小不能固定。例如,在深色模式下颜色需要反转,在智慧屏上字体需要放大。请问开发者如何利用 ArkUI 的特性来实现这种主题和字体大小的跨端自适应?

9 回复

HarmonyOS 6 提倡的“一次开发,多端部署”,并不意味着开发者手动为手机、平板、折叠屏、智慧屏分别维护一套主题和字体,而是通过 ArkUI 的资源体系、主题机制和响应式布局能力 实现自动适配。

1. 主题色不要写死

不推荐:

Text('标题')
  .fontColor('#007DFF')

因为:

  • 深色模式无法自动适配
  • 系统主题切换无法响应
  • 不同设备显示效果不一致

推荐使用资源引用:

Text('标题')
  .fontColor($r('sys.color.font_primary'))

或者:

.backgroundColor($r('app.color.primary_color'))

通过资源管理实现主题切换。


2. 使用深浅色资源

HarmonyOS支持为同一个资源配置:

resources
├─ base
│   └─ element
│       └─ color.json
├─ dark
│   └─ element
│       └─ color.json

例如:

base

{
  "color": [
    {
      "name": "page_background",
      "value": "#FFFFFF"
    }
  ]
}

dark

{
  "color": [
    {
      "name": "page_background",
      "value": "#000000"
    }
  ]
}

代码始终使用:

.backgroundColor($r('app.color.page_background'))

系统切换深色模式时自动生效。


3. 字体不要写固定像素

不推荐:

.fontSize(16)

在:

  • 手机
  • 平板
  • 智慧屏

上的视觉效果差异很大。

推荐使用:

.fontSize($r('app.float.font_body'))

或者设计系统中的字号资源。

例如:

{
  "float": [
    {
      "name": "font_body",
      "value": "16fp"
    }
  ]
}

使用 fp 单位后:

系统字体缩放
↓
ArkUI自动换算
↓
字体同步放大缩小

4. 响应系统字体大小

HarmonyOS支持用户在系统设置中调整字体大小。

开发时:

字体单位使用 fp

而不是:

vp
px

这样系统字体设置变化后:

标准
大号
超大号

应用会自动适配。


5. 根据设备类型调整字号

对于智慧屏场景:

3米观看距离

手机字号通常不够。

可以获取设备类型:

import { deviceInfo } from '@kit.BasicServicesKit'

根据设备类别:

if (deviceType === 'tv') {
  titleSize = 32
} else {
  titleSize = 20
}

或者通过断点能力:

GridRow({
  breakpoints: {
    reference: BreakpointsReference.WindowSize
  }
})

实现响应式适配。


6. 优先使用系统设计资源

HarmonyOS Design System 已提供:

sys.color.*
sys.float.*
sys.string.*

例如:

.fontColor($r('sys.color.font_primary'))
.backgroundColor($r('sys.color.comp_background_primary'))

这些资源已经适配:

  • 深浅色模式
  • 多设备显示
  • 系统主题

比自定义颜色更容易保持平台一致性。


7. 使用ArkUI主题机制

ArkUI支持全局主题配置:

Theme({
  colors: {
    primary: '#007DFF'
  }
})

应用内部统一引用主题色:

Button('确定')

系统会自动应用当前主题样式。

这样修改主题时:

修改一处
↓
全局生效

实践建议

对于 HarmonyOS 6 多端应用:

颜色

优先使用 sys.color
自定义颜色放资源文件
不要硬编码

字体

使用 fp
支持系统字体缩放
统一字号资源管理

布局

使用响应式布局
使用断点能力
避免固定尺寸

多端

手机:正常字号
平板:适度增大
智慧屏:明显增大

最终形成:

资源驱动主题
+
fp字体缩放
+
响应式布局
+
系统主题资源

这也是 HarmonyOS 6 “一次开发,多端部署”在主题色和字体适配方面的推荐实践。

更多关于HarmonyOS鸿蒙Next 6强调的“一次开发”理念,如何指导应用的主题色和字体大小的跨端自适应?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


背景知识:

主题色:

按照官方的要求,展示深色模式可以在 base/ 同级创建 dark/目录来展示深色模式对应的颜色如下:

cke_7867.png

然后通过全局控制对深色模式进控制:

示例代码:

// AppTheme.ets
import { CustomColors, CustomTheme, ThemeControl, Theme } from '@kit.ArkUI';

// 基础主题颜色(支持深浅色模式自适应)
export class AppBaseColors implements CustomColors {
  brand: ResourceColor = $r('app.color.brand_color');
  warning: ResourceColor = $r('app.color.warning_color');
  backgroundPrimary: ResourceColor = $r('app.color.background_primary');
  fontPrimary: ResourceColor = $r('app.color.font_primary');
}

// 全局主题
export class AppGlobalTheme implements CustomTheme {
  colors: AppBaseColors = new AppBaseColors();
}

// 全局主题实例
export const GlobalTheme = new AppGlobalTheme();

// 在应用启动时设置全局默认主题
ThemeControl.setDefaultTheme(GlobalTheme);


------ 设置深色模式

import { ConfigurationConstant } from '@kit.BasicServicesKit';

// 设置应用为深色模式
this.context.getApplicationContext().setColorMode(
  ConfigurationConstant.ColorMode.COLOR_MODE_DARK
);

// 设置为浅色模式
this.context.getApplicationContext().setColorMode(
  ConfigurationConstant.ColorMode.COLOR_MODE_LIGHT
);

// 跟随系统模式
this.context.getApplicationContext().setColorMode(
  ConfigurationConstant.ColorMode.COLOR_MODE_FOLLOW_SYSTEM
);

字体大小:

1、HarmonyOS 使用 fp 作为字体专用单位,具有以下特性:

特性 说明
默认规则 1fp = 1vp(视觉像素单位)
系统缩放 实际字体大小 = vp值 × 系统字体缩放比例
示例 用户将系统字体放大至 1.5 倍,则 16fp 实际显示为 16vp × 1.5 = 24vp

2、所以可以在:base/profile/configuration.json配置:

{
  "configuration": {
    "fontSizeScale": "followSystem",  // 开启跟随系统字体缩放
    "fontSizeMaxScale": "3.2"         // 最大缩放倍数限制
  }
}

3、设备差异化字体大小:

针对不同设备类型(手机、平板、智慧屏),使用断点系统实现差异化字体大小:

示例代码:

// BreakpointSystem.ets
@ObservedV2
class BreakpointState {
  @Trace currentBreakpoint: string = 'sm'; // xs/sm/md/lg/xl
}

// 断点类型映射工具
export class BreakpointType<T> {
  private options: { xs?: T; sm?: T; md?: T; lg?: T; xl?: T };
  
  constructor(options: { xs?: T; sm?: T; md?: T; lg?: T; xl?: T }) {
    this.options = options;
  }
  
  getValue(breakpoint: string): T | undefined {
    if (breakpoint === 'xs') return this.options.xs;
    if (breakpoint === 'sm') return this.options.sm;
    if (breakpoint === 'md') return this.options.md;
    if (breakpoint === 'lg') return this.options.lg;
    if (breakpoint === 'xl') return this.options.xl;
    return undefined;
  }
}

智慧屏字体放大例子:

@Component
export struct AdaptiveTextPage {
  @StorageProp('currentBreakpoint') currentBreakpoint: string = 'sm';

  build() {
    Column() {
      // 标题文本:智慧屏(lg)上字体放大
      Text('智慧屏大字体标题')
        .fontSize(
          new BreakpointType({
            xs: 18,  // 穿戴设备
            sm: 20,  // 手机
            md: 24,  // 平板竖屏
            lg: 32,  // 智慧屏/平板横屏(放大)
            xl: 36   // 超大屏设备
          }).getValue(this.currentBreakpoint) || 20
        )
        .fontWeight(FontWeight.Bold)

      // 正文文本:智慧屏上同样放大
      Text('这是一段正文内容,在智慧屏上会自动放大字体以提升阅读体验。')
        .fontSize(
          new BreakpointType({
            xs: 12,
            sm: 14,
            md: 16,
            lg: 20,  // 智慧屏放大
            xl: 22
          }).getValue(this.currentBreakpoint) || 14
        )
    }
    .width('100%')
    .padding(20)
  }
}

ArkUI 为多端部署提供了完善的主题适配、响应式字体、深色模式、设备差异化能力。
核心思路是:不写死硬编码值,全部使用动态可配置的资源 + 系统和设备感知能力。
这是实现跨端主题 / 字体自适应的基础:

  1. 资源限定词(Resource)
    按设备类型、屏幕尺寸、深色模式自动匹配对应资源(颜色、字体、尺寸),无需代码判断。
  2. ArkTS 资源引用 $r()
    统一引用资源文件,系统自动根据当前环境(深色 / 设备)加载对应值。
  3. 响应式布局单位(vp、百分比)
    vp:虚拟像素,自动适配不同屏幕密度
  4. 主题配置 + 状态监听
    监听系统深色模式、设备类型、字体大小变化,实时刷新 UI。

建议研读《ArkUI 方舟UI框架》《构建布局》

找HarmonyOS工作还需要会Flutter的哦,有需要Flutter教程的可以学学大地老师的教程,很不错,B站免费学的哦:https://www.bilibili.com/video/BV1S4411E7LY/?p=17,

一次开发不是把同一套固定颜色和字号硬搬到所有设备,而是把颜色、字号、间距做成语义化资源,再让系统模式和设备断点去选择。

颜色上建议使用资源目录区分 light/dark,或用系统语义色/自定义 token,例如 background、textPrimary、brandPrimary,不要在组件里大量写死 #fff/#000。字号上优先用 fp,允许跟随系统字体缩放;大屏、平板、智慧屏可以再结合断点或资源限定目录调整标题、正文、列表密度。

布局层面也要配合 GridRow、媒体查询/断点状态、百分比宽度等方式,让“主题自适应”和“版式自适应”一起生效。

一次开发不是把同一套像素硬搬到所有设备上,而是把“语义资源”和“断点布局”拆开。颜色不要写死 #000/#fff,建议在 base/element/color.json 和 dark/element/color.json 定义同名 token,页面只引用语义色:

Text(‘标题’) .fontColor($r(‘app.color.text_primary’)) .backgroundColor($r(‘app.color.page_bg’))

系统切换深色模式时会加载 dark 目录下的同名资源,业务代码不需要到处 if。字体和布局则按断点/设备能力调 token,例如手机 20fp、平板 24fp、智慧屏 28fp;结构上用 GridRow/GridCol 的 sm/md/lg span 做响应式排列。

可以理解为:颜色交给资源限定词,字号交给字体 token,排版交给断点。这样主题切换、显示缩放、横竖屏或窗口大小变化时,页面不会像贴图一样被拉扯变形。参考来源:官方《深色模式适配》《响应式布局》。

开发者您好,针对您关注的两个问题:

1、深色模式下颜色需要反转的需求可参考实战文章:

鸿蒙开发入门:如何适配深色模式之颜色篇

https://developer.huawei.com/consumer/cn/blog//topic/03212842464249225

2、字体大小设置vp为单位,可以达到不同机器自适应,当数值不带单位时,默认单位vp。可参考示例:

https://developer.huawei.com/consumer/cn/doc/harmonyos-references/ts-pixel-units#示例

在HarmonyOS Next的ArkUI框架下,“一次开发”理念通过声明式UI和自适应布局能力实现跨端适配。主题色自适应可通过资源限定词(如colorMode)和响应式设计,结合@Styles@Extend动态切换。字体大小自适应使用vp(虚拟像素)和fp(字体像素)单位,配合媒体查询(如@Media断点)适配不同屏幕密度与缩放。无需碎片化编码,统一配置即可全局生效。

在 ArkUI 中,遵循“一次开发”理念实现主题色与字体跨端自适应的核心是资源限定符响应式单位的配合,开发者无需编写复杂逻辑即可让系统自动匹配。

  1. 主题色自适应:利用资源目录的限定符(如 dark/element/color.json)定义深色模式下的颜色值,使用 $r('app.color.xxx') 引用。系统会根据当前颜色模式(深色/浅色)自动加载对应资源。如需自定义主题切换,可通过 AppStorage 感知 darkMode 变化并动态更新绑定的全局样式变量。
  2. 字体大小跨端适配:使用 fp(字体像素)作为单位,它会随系统缩放比例变化,保证无障碍阅读。对于智慧屏等大屏,可在 resources 目录下建立如 sw600dpsw840dp 等最小宽度限定符,在其中定义更大的 fontSize 值,ArkUI 在运行时根据不同设备宽度自动选择对应资源。
  3. 一次开发的落地:所有差异仅体现在资源文件中,业务代码通过 $r 引用或 @StorageLink 绑定,无需针对不同端硬编码样式。配合 vp 单位和 @Styles / @Extend 复用样式,即可真正做到写一次逻辑,主题与字体随端而变。
// 资源文件: resources/dark/element/color.json
{
  "color": [
    { "name": "text_primary", "value": "#FFFFFFFF" }
  ]
}
// 页面引用
Text('内容').fontColor($r('app.color.text_primary')).fontSize($r('app.float.font_body'))
回到顶部