你有没有过这样的经历——给爸妈换了新手机,结果他们连微信都看不清字?按钮太小、文字太密、颜色对比度不够……年轻人觉得好看的设计,对长辈来说简直是"视力测试"。HarmonyOS 7.0(API 26)新增的关怀模式能力,就是专门来解决这个问题的。

一、关怀模式是个啥?

关怀模式(也叫长辈模式、大字版、关爱版、敬老版……名字很多,核心一样)本质上就是一套适老化UI适配方案。开启后,应用需要做到:

  • 文字更大:标题、正文、按钮文字都要放大
  • 间距更宽:列表行高、卡片间距都要拉开
  • 对比度更高:背景和文字颜色区分更明显
  • 按钮更大:点击目标区域更大,手抖也不怕误触
  • 层级更少:常用功能一步到位,减少深层嵌套

HarmonyOS 7.0给开发者提供了两套接口,让App的关怀模式状态能跟系统设置实时同步。
请添加图片描述

二、两种对接方式,选哪个?

方式 适用场景 接口来源
跟随系统 App内没有独立开关,系统开了关怀模式就跟着开 isSeniorModeEnabled() / onSeniorModeStateChange()
独立控制 App内有自己的关怀模式开关,但要让系统"设置"页面也能管 getSeniorModeStateForSelf() / setSeniorModeStateForSelf() / onSeniorModeStateChangeForSelf()

简单说:

  • 你App里没有关怀模式开关 → 用跟随系统那套
  • 你App里有关怀模式开关 → 用独立控制那套,并且要在module.json5里声明metadata

三、配置声明:让系统知道你支持关怀模式

module.json5 里加上metadata声明,这样用户就能在**“设置 > 关怀和无障碍 > 关怀模式 > 应用管理”**里看到你的App:

{
  "module": {
    // ... 其他配置
    "metadata": [
      {
        "name": "senior_mode",
        "value": "independent_control"
      }
    ]
  }
}

⚠️ 注意:声明了 independent_control 就意味着你App内有独立开关,需要用 getSeniorModeStateForSelf / setSeniorModeStateForSelf 那套接口来同步状态。如果你只是想跟随系统,不声明这个metadata就行。

还有个重要规则:用户在系统设置里关闭关怀模式,所有App的关怀模式都会跟着关;重新开启系统关怀模式时,原先被关闭的App会同步恢复开启。这个是系统级行为,不需要你额外处理。

四、核心接口速查

4.1 跟随系统模式

接口 说明
isSeniorModeEnabled(): Promise<boolean> 查询系统关怀模式是否开启
onSeniorModeStateChange(callback: Callback<boolean>): void 监听系统关怀模式变化
offSeniorModeStateChange(callback?: Callback<boolean>): void 取消监听

4.2 独立控制模式

接口 说明
getSeniorModeStateForSelf(): Promise<boolean> 查询"设置"中本App关怀模式开关状态
setSeniorModeStateForSelf(state: boolean): Promise<void> 设置"设置"中本App关怀模式开关状态
onSeniorModeStateChangeForSelf(callback: Callback<boolean>): void 监听"设置"中本App关怀模式开关变化
offSeniorModeStateChangeForSelf(callback?: Callback<boolean>): void 取消监听

两套接口的命名很直观:没有"ForSelf"的是系统级的,带"ForSelf"的是本App自己的。

五、实战Demo:普通模式 vs 关怀模式,效果一目了然

光说概念没感觉,直接上代码。下面这个Demo展示了一个简单的"生活服务"页面,在普通模式和关怀模式下的视觉差异非常明显:

  • 普通模式:正常字号、正常间距、标准配色
  • 关怀模式:大字号、宽间距、高对比度、大按钮、简化布局
import { accessibility } from '@kit.AccessibilityKit';
import { BusinessError } from '@kit.BasicServicesKit';

interface ServiceItem {
  icon: string;
  title: string;
  desc: string;
}

@Entry
@Component
struct SeniorModeDemo {
  @State isSeniorMode: boolean = false;
  private seniorModeCallback = (data: boolean) => {
    this.isSeniorMode = data;
  };

  async aboutToAppear(): Promise<void> {
    try {
      this.isSeniorMode = await accessibility.isSeniorModeEnabled();
    } catch (e) {
      const err = e as BusinessError;
      console.error(`isSeniorModeEnabled failed: ${err.code}, ${err.message}`);
    }
    accessibility.onSeniorModeStateChange(this.seniorModeCallback);
  }

  aboutToDisappear(): void {
    accessibility.offSeniorModeStateChange(this.seniorModeCallback);
  }

  build() {
    Column() {
      // 顶部标题栏
      Row() {
        Text('生活服务')
          .fontSize(this.isSeniorMode ? 28 : 20)
          .fontWeight(FontWeight.Bold)
          .fontColor('#1a1a1a')
        Blank()
        Text(this.isSeniorMode ? '关怀模式已开启' : '普通模式')
          .fontSize(this.isSeniorMode ? 16 : 12)
          .fontColor(this.isSeniorMode ? '#e65100' : '#999999')
          .padding({ left: 8, right: 8, top: 4, bottom: 4 })
          .borderRadius(12)
          .backgroundColor(this.isSeniorMode ? '#fff3e0' : '#f5f5f5')
      }
      .width('100%')
      .padding({ left: 16, right: 16, top: this.isSeniorMode ? 24 : 12, bottom: this.isSeniorMode ? 20 : 12 })

      // 快捷服务区
      Grid() {
        ForEach(this.getServiceItems(), (item: ServiceItem) => {
          GridItem() {
            Column() {
              Text(item.icon)
                .fontSize(this.isSeniorMode ? 40 : 28)
              Text(item.title)
                .fontSize(this.isSeniorMode ? 18 : 14)
                .fontWeight(this.isSeniorMode ? FontWeight.Bold : FontWeight.Normal)
                .fontColor('#333333')
                .margin({ top: this.isSeniorMode ? 12 : 6 })
            }
            .width('100%')
            .padding(this.isSeniorMode ? 20 : 12)
            .borderRadius(12)
            .backgroundColor('#ffffff')
            .justifyContent(FlexAlign.Center)
          }
        })
      }
      .columnsTemplate('1fr 1fr 1fr 1fr')
      .rowsGap(this.isSeniorMode ? 16 : 8)
      .columnsGap(this.isSeniorMode ? 16 : 8)
      .width('100%')
      .padding({ left: 16, right: 16 })
      .height(this.isSeniorMode ? 240 : 180)

      // 信息卡片列表
      Column() {
        ForEach(this.getInfoCards(), (card: ServiceItem) => {
          Row() {
            Column() {
              Text(card.title)
                .fontSize(this.isSeniorMode ? 20 : 16)
                .fontWeight(FontWeight.Medium)
                .fontColor('#1a1a1a')
              Text(card.desc)
                .fontSize(this.isSeniorMode ? 16 : 13)
                .fontColor(this.isSeniorMode ? '#333333' : '#888888')
                .margin({ top: this.isSeniorMode ? 8 : 4 })
            }
            .layoutWeight(1)
            .alignItems(HorizontalAlign.Start)

            Text('>')
              .fontSize(this.isSeniorMode ? 24 : 16)
              .fontColor('#cccccc')
          }
          .width('100%')
          .padding(this.isSeniorMode ? 24 : 16)
          .margin({ top: this.isSeniorMode ? 12 : 8 })
          .borderRadius(12)
          .backgroundColor('#ffffff')
        })
      }
      .width('100%')
      .padding({ left: 16, right: 16 })
      .layoutWeight(1)

      // 底部操作按钮
      Button('一键呼叫家人')
        .width(this.isSeniorMode ? '90%' : '60%')
        .height(this.isSeniorMode ? 64 : 44)
        .fontSize(this.isSeniorMode ? 22 : 16)
        .fontWeight(FontWeight.Bold)
        .backgroundColor('#e65100')
        .fontColor('#ffffff')
        .borderRadius(this.isSeniorMode ? 32 : 22)
        .margin({ top: 16, bottom: this.isSeniorMode ? 40 : 24 })

      Text('请在系统"设置 > 关怀和无障碍"中切换关怀模式')
        .fontSize(this.isSeniorMode ? 14 : 11)
        .fontColor('#bbbbbb')
        .margin({ bottom: this.isSeniorMode ? 24 : 16 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor(this.isSeniorMode ? '#fff8f0' : '#f5f5f5')
  }

  private getServiceItems(): ServiceItem[] {
    return [
      { icon: '🏥', title: '医院挂号', desc: '' },
      { icon: '💊', title: '药品购买', desc: '' },
      { icon: '🚌', title: '公交查询', desc: '' },
      { icon: '☎️', title: '联系家人', desc: '' },
      { icon: '🌤', title: '天气预报', desc: '' },
      { icon: '📺', title: '电视节目', desc: '' },
      { icon: '📋', title: '体检报告', desc: '' },
      { icon: '🔔', title: '吃药提醒', desc: '' },
    ];
  }

  private getInfoCards(): ServiceItem[] {
    return [
      { icon: '', title: '今日健康提示', desc: '血压正常范围:收缩压90-140mmHg,舒张压60-90mmHg' },
      { icon: '', title: '用药提醒', desc: '降压药每日早8点服用,请勿空腹' },
      { icon: '', title: '社区活动', desc: '周三上午9点,社区广场太极拳免费教学' },
    ];
  }
}

请添加图片描述

六、普通模式 vs 关怀模式:关键差异对比

维度 普通模式 关怀模式
标题字号 20fp 28fp(+40%)
正文字号 13-16fp 16-20fp(+23%~+25%)
图标大小 28 40(+43%)
卡片内边距 12-16dp 20-24dp(+50%)
列表行高间距 8dp 16dp(+100%)
描述文字颜色 #888888 #333333(对比度更高)
页面背景色 #f5f5f5 #fff8f0(暖色调,更护眼)
按钮高度 44dp 64dp(+45%)
按钮宽度 60% 90%(更容易点到)
操作按钮字号 16fp 22fp(+37%)

核心思路就一句话:关怀模式下,所有元素都更大、更宽、更醒目。
请添加图片描述

七、开发避坑指南

  1. 别用绝对尺寸:用变量控制字号和间距,不要硬编码。推荐用一个 isSeniorMode 布尔值来驱动所有UI尺寸变化,就像Demo里那样。

  2. 监听生命周期要对onSeniorModeStateChangeaboutToAppear 注册,aboutToDisappear 一定要取消,否则内存泄漏。

  3. 初始化要查状态:用户可能在App外面改了系统设置,App冷启动时要用 isSeniorModeEnabled() 主动查一次,别只依赖监听。

  4. 独立控制要声明metadata:如果你用了 setSeniorModeStateForSelf,必须同时在module.json5声明 senior_mode: independent_control,否则设置页面看不到你的App。

  5. 系统级关闭不可抗拒:用户在系统设置关闭关怀模式时,所有App的关怀模式都会被强制关闭,这个是系统行为,你拦不住,也没必要拦。

  6. 色彩对比度要达标:关怀模式不只是"放大",对比度同样重要。灰色文字在关怀模式下要换成深色(比如#888→#333),浅色背景可以换成暖色调。

  7. 交互简化:关怀模式下,减少操作层级。常用功能放首页,深层功能可以隐藏。按钮要大,最好有明确的文字标签而不是纯图标。

八、最佳实践:一套代码,两种体验

推荐的做法是定义一组设计Token,根据 isSeniorMode 动态切换:

// 设计Token,集中管理所有尺寸和颜色
function getDesignToken(isSenior: boolean) {
  return {
    // 字号
    fontTitle: isSenior ? 28 : 20,
    fontBody: isSenior ? 18 : 14,
    fontDesc: isSenior ? 16 : 12,
    fontButton: isSenior ? 22 : 16,

    // 间距
    paddingCard: isSenior ? 24 : 16,
    gapRow: isSenior ? 16 : 8,
    marginSection: isSenior ? 20 : 12,

    // 尺寸
    buttonHeight: isSenior ? 64 : 44,
    iconSize: isSenior ? 40 : 28,

    // 颜色
    textPrimary: '#1a1a1a',
    textSecondary: isSenior ? '#333333' : '#888888',
    background: isSenior ? '#fff8f0' : '#f5f5f5',
    accent: '#e65100',
  };
}

这样整个App只需要一个布尔值驱动,所有页面自动适配,维护起来也方便。

九、总结

HarmonyOS 7.0的关怀模式能力,本质上是把"适老化"从"应用各自为战"变成了"系统级统管"。开发者要做的就是:

  1. 声明metadata,告诉系统你支持关怀模式
  2. 监听状态变化,实时响应系统设置
  3. UI自适应,根据模式切换字号、间距、颜色
  4. 交互简化,让长辈少点、少等、少迷路

这不仅是技术问题,更是产品态度。中国2.8亿60岁以上人口,适老化不是可选项,是必选项。HarmonyOS 7.0给了基础设施,剩下的就看我们开发者的诚意了。


本文基于HarmonyOS API 26(7.0)编写,关怀模式相关接口起始版本为26.0.0。Demo代码可直接复制到ArkTS工程中运行,需要在系统设置中开启关怀模式查看效果。

Logo

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

更多推荐