本节目标· 理解资源限定词机制掌握多语言资源的目录组织与 $r() 引用方式· 掌握复数处理、日期/数字/货币的区域化格式化方法· 掌握应用内运行时语言切换的实现方式理解持久化语言偏好的必要性· 掌握无障碍属性配置能够为文本类与非文本类组件正确设置屏幕朗读内容· 理解 accessibilityGroup、accessibilityText、accessibilityDescription 等属性的适用场景· 掌握 RTL 镜像布局的适配方法能够将绝对方向布局改造为 start/end 相对方向布局· 理解多设备适配的断点系统掌握 GridRow GridCol 栅格布局的实现方式· 能够为一个应用建立完整的国际化、无障碍与多设备适配方案一、资源管理与多语言适配1.1 为什么不能硬编码把界面上的文字、颜色和图片直接写进 ArkTS短期看很省事一旦应用需要切换语言、适配深色模式或调整品牌视觉散落在页面里的硬编码就会迅速成为维护负担。具体来说硬编码至少带来以下问题文案散落在代码中翻译人员难以统一处理深色模式切换时需要在多个组件中手动判断颜色图片路径与业务代码耦合相同文案重复出现无法保证用词一致。更稳妥的方式是让 ArkTS 只引用资源标识把具体内容交给资源系统管理。1.2 资源目录结构Stage 模型的模块资源通常位于 entry/src/main/resources核心结构如下entry/src/main/resources/ ├── base/ # 默认资源目录兜底 │ ├── element/ │ │ ├── string.json # 字符串资源 │ │ ├── color.json # 颜色资源 │ │ ├── float.json # 尺寸资源 │ │ └── plural.json # 复数资源 │ ├── media/ # 图片资源 │ └── profile/ # 页面配置 ├── zh_CN/ # 中文限定目录 │ └── element/string.json ├── en_US/ # 英文限定目录 │ └── element/string.json └── dark/ # 深色模式限定目录 └── element/color.jsonbase 是默认资源目录。当更具体的限定词目录没有匹配内容时系统会回退到 base。zh_CN、en_US 是语言与地区限定目录dark 用于深色模式。资源目录名称和文件格式有固定约定不建议自行创建任意层级来代替限定词目录。1.3 定义与引用字符串资源在 base/element/string.json 中准备默认文案{string:[{name:profile_title,value:个人中心},{name:welcome_user,value:你好%s},{name:save,value:保存}]}在 ArkUI 组件中通过 $r 引用EntryComponentstruct ProfilePage{build(){Column({space:16}){Text($r(app.string.profile_title)).fontSize(22).fontWeight(FontWeight.Bold)Button($r(app.string.save))}.width(100%).padding(20)}}app 表示应用资源string 表示资源类型末尾是资源名。资源名应表达语义例如 profile_title不要使用 text1、label_a 这类难以维护的名称。$r 引用要求 name 必须在所有语言目录中保持一致只允许 value 不同。1.4 资源键命名规范推荐使用语义化键名{name:mode_time_attack_desc,value:分秒必争限时收集挑战}不推荐把键命名为拼音或 text1、label2。语义键让开发者无需打开 JSON 就知道用途也能区分同一个中文词在不同上下文中的翻译。按钮、标题、描述和提示应使用不同键——很多语言的词形会随上下文变化不能因为中文看起来相同就强行复用。1.5 复数处理对于涉及数量变化的文案可使用 plural.json 定义复数资源运行时按数量选择文案{plural:[{name:file_count,value:[{quantity:one,value:%d 个文件},{quantity:other,value:%d 个文件}]}]}或使用 resourceManager.getPluralStringValue(id, num) 获取复数化字符串。1.6 日期、数字、货币的区域化使用 ohos.intl 进行本地化格式化避免硬编码格式import{intl}fromkit.LocalizationKit;// 日期格式化constdateFmtnewintl.DateTimeFormat(zh-CN,{dateStyle:medium,timeStyle:short});constdateStrdateFmt.format(newDate());// 货币格式化constnumFmtnewintl.NumberFormat(zh-CN,{style:currency,currency:CNY});constpriceStrnumFmt.format(199.99);二、无障碍适配2.1 无障碍能力概述HarmonyOS 系统提供了屏幕朗读、大字体、高对比度文字、色彩校正、颜色反转、单声道音频、音量平衡、屏幕触控等一整套无障碍系统服务。开发者的核心任务是让屏幕朗读能够正确提取和播报界面元素信息。无障碍文本的优先级大于显示文本即当无障碍文本不为空时会朗读无障碍文本否则朗读显示文本。2.2 accessibilityText 无障碍文本accessibilityText 用于为组件设置屏幕朗读的文本内容。当组件不包含可被屏幕朗读的文本属性如 Image 等本身不直接显示文本的组件时屏幕朗读选中此组件时不播报使用者无法清楚地知道当前选中了什么组件。为解决此问题开发人员可为不包含文本属性的组件设置无障碍文本。// 非文本类控件使用 accessibilityText 提供朗读信息Image($r(app.media.banner)).width(100%).height(200).accessibilityText(首页轮播图新用户专享优惠活动)// 文本类控件如额外提供颜色等视觉信息可用无障碍文本补充Button(提交).accessibilityText(提交表单点击后将验证并保存信息)设计规则对于文本类控件尽量使用显示文本来表达信息使视障用户和视力健全用户可以获取到相同的信息。如果除显示文本外还额外提供了颜色等视觉效果可采用无障碍文本为视障用户提供更多信息。对于非文本类控件可采用无障碍文本为视障用户提供朗读信息。2.3 accessibilityGroup 无障碍分组accessibilityGroup 设置为 true 时表示该组件及其所有子组件为一个整体的可选中组件无障碍辅助服务将不再关注其子组件内容。若组件启用无障碍分组当组件不包含通用文本属性且未设置无障碍文本时将默认拼接其子组件的通用文本属性作为组件的合并文本。若某一子组件没有通用文本属性则忽略该子组件不进行拼接。// 将日期、天气、温度等多个信息合并为一个可选中组件Row(){Text(周一).fontSize(14)Text(晴).fontSize(14)Text(25°C).fontSize(14)}.accessibilityGroup(true).accessibilityText(周一晴天气温25度)典型场景默认只有子组件才能获取焦点日期、天气、温度等信息在每个组件独立获取焦点时分别朗读体验不佳。将 accessibilityGroup 设置为 true 后子组件无法获取焦点整个卡片作为一个整体被选中朗读。2.4 accessibilityDescription 无障碍说明accessibilityDescription 用于为用户进一步说明当前组件尤其是当操作后果无法从组件本身属性与无障碍文本中了解到时。组件被选中时先播报组件的文本属性或 accessibilityText再播报无障碍说明属性的内容。Button(删除).accessibilityDescription(点击此按钮将永久删除当前条目操作不可撤销)2.5 accessibilityLevel 无障碍重要性accessibilityLevel 用于控制某个组件是否可被无障碍辅助服务所识别auto 由系统根据组件类型自动决定是否可被识别默认为该值。yes 当前组件可被无障碍辅助服务选中。no 当前组件不可被无障碍辅助服务选中。no-hide-descendants 无障碍辅助服务忽略当前组件及其所有子组件。// 装饰性图片无需被屏幕朗读选中Image($r(app.media.decorative_line)).accessibilityLevel(no)// 容器组件默认不会被选中如需使其可被选中Column(){// 自定义组件内容}.accessibilityLevel(yes).accessibilityGroup(true).accessibilityText(自定义组件描述)2.6 无障碍焦点顺序与最佳实践屏幕朗读适配的核心是“聚焦有序 朗读清晰”确保视障用户逻辑导航和信息获取无障碍。一个业务控件应暴露一个清晰的可朗读节点避免父子都可访问造成顺序异常或重复播报。最佳实践要点为所有图片添加 accessibilityText 描述内容。使用 accessibilityGroup(true) 将逻辑上属于同一信息的多个子组件合并为一个焦点单元。使用 accessibilityDescription 说明操作后果如“删除”“提交”等按钮。装饰性元素设置 accessibilityLevel(‘no’) 避免冗余播报。通过 accessibilityNextFocusId 控制焦点顺序API 18确保朗读顺序符合视觉逻辑。三、RTL 镜像布局适配3.1 RTL 布局的基本概念不同国家对文本对齐方式和读取顺序有所不同例如英语采用从左到右LTR的顺序阿拉伯语和希腊语则采用从右到左RTL的顺序。为满足不同用户的阅读习惯ArkUI 提供了镜像能力在特定情况下将显示内容在 X 轴上进行镜像反转由从左到右显示变成从右到左显示。当组件满足以下任意条件时镜像能力生效组件的 direction 属性设置为 Direction.Rtl。组件的 direction 属性设置为 Direction.Auto且当前的系统语言如维吾尔语、阿拉伯语的阅读习惯是从右向左。3.2 全局 RTL 设置在应用入口通过 Configuration 设置全局布局方向为 RTL// 方式一设置应用级布局方向import{ConfigurationConstant}fromkit.AbilityKit;// 在 EntryAbility 中设置onCreate(want:Want,launchParam:AbilityConstant.LaunchParam):void{// 系统语言为 RTL 时自动生效}组件级设置Row().direction(Direction.Rtl)// 强制 RTLColumn().direction(Direction.Auto)// 自动跟随系统语言3.3 使用 start/end 替代 left/rightRTL 适配的关键是将所有绝对方向的描述改为相对方向的描述即使用 start 和 end 替代 left 和 right。ArkUI 的通用属性中以下属性需要使用新入参类型适配尺寸设置padding、margin 使用 start / end 替代 left / right。位置设置position 使用 start / top 替代 x / y。import{LengthMetrics}fromkit.ArkUI;// ❌ 不推荐使用绝对方向Column().padding({left:16,right:16}).margin({left:20})// ✅ 推荐使用 start/end 相对方向自动适配 RTLColumn().padding({start:LengthMetrics.vp(16),end:LengthMetrics.vp(16)}).margin({start:LengthMetrics.vp(20)})需要同时支持 LTR 和 RTL 时使用 API 12 新增的 LocalizedEdges 入参类型仅支持 LTR 时等同于原来的 x/y 设置。3.4 RelativeContainer 的对齐适配在 RelativeContainer 中alignRules 提供 start 和 end 方向的对齐规则替换原来的 left 和 right 方向参数以支持 RTL 布局的镜像。RelativeContainer(){Text(内容).alignRules({start:{anchor:__container__,align:HorizontalAlign.Start},top:{anchor:__container__,align:VerticalAlign.Top}})}3.5 Canvas 的 RTL 处理Canvas 组件的绘制内容和坐标均不支持自动镜像已绘制到 Canvas 上的内容不会跟随系统语言切换自动做镜像效果。需要应用监听到系统语言切换后自行重新绘制。CanvasRenderingContext2D 的文本绘制支持镜像能力其 direction 属性优先级高于 Canvas 组件的 direction 属性。3.6 RTL 适配检查清单支持 RTL 不仅仅是文字方向的切换更是整个 UI 布局的镜像翻转——导航栏、按钮排列、列表滑动方向都需要相应调整。上线前建议逐项检查所有 padding / margin 是否已改为 start / end。所有 position 是否已改为 start / top。图片资源中是否包含方向性图标如箭头、返回按钮需要单独提供 RTL 版本。列表滑动删除方向是否正确。RelativeContainer 的 alignRules 是否使用了 start / end。四、多设备适配4.1 断点系统HarmonyOS 提供了一套断点系统用来根据设备宽度做布局适配。栅格布局可以为布局提供规律性的结构解决多尺寸多设备的动态布局问题保证不同设备上各个模块的布局一致性。常用断点划分如下· xs超小屏 宽度 320vp· sm小屏 320vp ≤ 宽度 600vp对应手机竖屏· md中屏 600vp ≤ 宽度 840vp对应手机横屏、折叠屏展开态· lg大屏 宽度 ≥ 840vp对应平板、PC4.2 GridRow 栅格布局GridRow 是栅格行布局容器仅可以和栅格子组件 GridCol 在栅格布局场景中使用支持根据设备尺寸和断点动态调整列数与间距实现响应式布局。EntryComponentstruct GridLayoutDemo{build(){GridRow({columns:{xs:2,sm:4,md:8,lg:12},// 不同断点下的列数gutter:{x:12,y:12},// 间距breakpoints:{value:[320vp,600vp,840vp]}}){GridCol({span:{xs:2,sm:2,md:4,lg:6}}){this.card(卡片一,#E8F0FE)}GridCol({span:{xs:2,sm:2,md:4,lg:6}}){this.card(卡片二,#FEF0E8)}}.width(100%).padding(16)}Buildercard(title:string,bgColor:string){Column(){Text(title).fontSize(18).fontWeight(FontWeight.Bold)}.width(100%).height(120).backgroundColor(bgColor).borderRadius(12).justifyContent(FlexAlign.Center)}}columns 支持按断点设置不同列数gutter 设置栅格间距breakpoints 自定义断点位置。GridCol 的 span 属性支持按断点设置子组件占用的列数。4.3 媒体查询动态适配使用 mediaquery 模块可以监听窗口尺寸变化动态调整 UI 布局import{mediaquery}fromkit.ArkUI;EntryComponentstruct ResponsivePage{StatecurrentBreakpoint:stringsm;privatelistener:mediaquery.MediaQueryListener|nullnull;aboutToAppear():void{this.listenermediaquery.matchMediaSync((width840vp));this.listener.on(change,(result:mediaquery.MediaQueryResult){this.currentBreakpointresult.matches?lg:sm;});}aboutToDisappear():void{this.listener?.off(change);}build(){Column(){if(this.currentBreakpointlg){// 大屏布局分栏展示Row(){this.sidePanel()this.mainContent()}}else{// 小屏布局单栏展示this.mainContent()}}.width(100%).height(100%)}BuildersidePanel(){Column().width(240).height(100%).backgroundColor(#F5F5F5)}BuildermainContent(){Column().layoutWeight(1).height(100%).backgroundColor(Color.White)}}当检测到窗口尺寸跨越断点时触发组件实例的布局重计算和样式切换实现从手机竖屏到横屏、折叠屏折叠状态切换以及窗口分屏等场景布局转换的实时适配。4.4 多设备适配最佳实践布局统一使用 GridRow 栅格 sm / md / lg 断点尺寸单位全用 vp/fp 不用 px再配合 ohos.mediaquery 监听屏幕变化做局部调整。组件样式尽量抽成资源文件color/size 按 dpi 分目录这样大部分页面不用为每个设备单独写样式。UI 复杂的地方再用 onWindowSizeChange 做分屏/折叠特判。五、多元化习题习题 1判断题题目在 ArkUI 中$r(‘app.string.xxx’) 引用资源时资源名 xxx 可以在不同语言目录中使用不同的名称。答案错误解读$r 引用要求 name 必须在所有语言目录中保持一致只允许 value 不同。系统根据当前语言环境匹配对应目录中的同名资源如果名称不一致则无法正确匹配。习题 2单选题题目以下哪个属性用于控制组件是否可被无障碍辅助服务识别A. accessibilityTextB. accessibilityGroupC. accessibilityLevelD. accessibilityDescription答案C解读accessibilityLevel 用于控制某个组件是否可被无障碍辅助服务所识别。accessibilityText 设置无障碍文本accessibilityGroup 设置无障碍分组accessibilityDescription 设置无障碍说明。习题 3多选题题目关于 RTL 镜像布局适配以下说法正确的有多选A. 组件 direction 属性设置为 Direction.Rtl 时镜像能力生效B. 在 RTL 布局中left / right 会自动切换为 start / endC. 建议使用 start / end 替代 left / right 以支持 RTLD. Canvas 组件的内容会自动跟随系统语言切换做镜像答案A、C解读组件 direction 设置为 Direction.Rtl 时镜像能力生效选项 A 正确。在 RTL 布局中left / right 不会自动切换需要开发者使用 start / end 替代选项 B 错误选项 C 正确。Canvas 组件的绘制内容和坐标均不支持自动镜像需要应用监听到系统语言切换后自行重新绘制选项 D 错误。习题 4代码填空题题目请补全以下代码使 Image 组件在屏幕朗读时能够被正确播报。Image($r(app.media.banner)).width(100%).height(200)// 在此处填写代码设置无障碍文本______________答案.accessibilityText(‘首页轮播图新用户专享优惠活动’)解读Image 组件本身不直接显示文本屏幕朗读选中此组件时不播报。需要为不包含文本属性的组件设置无障碍文本当屏幕朗读选中此组件时播报无障碍文本的内容。习题 5代码改错题题目以下代码存在国际化适配问题请指出问题并修正。Column(){Text(个人信息).fontSize(20).fontColor(#333333)Text(姓名张三).fontSize(16)}.padding({left:16,right:16}).margin({left:20})答案代码存在两个问题。第一文字内容硬编码无法适配多语言第二padding 和 margin 使用了 left / right 绝对方向无法适配 RTL 布局。修正如下Column(){Text($r(app.string.profile_info)).fontSize(20).fontColor($r(app.color.text_primary))Text($r(app.string.name_label,{name:张三})).fontSize(16)}.padding({start:LengthMetrics.vp(16),end:LengthMetrics.vp(16)}).margin({start:LengthMetrics.vp(20)})解读所有界面文字应使用 $r 引用资源便于多语言翻译所有方向性属性应使用 start / end 替代 left / right以便在 RTL 语言下自动镜像。习题 6简答题题目简述资源限定词机制的工作原理以及 base 目录的作用。答案资源限定词机制通过在 resources 目录下创建带有限定词的子目录如 zh_CN、en_US、dark、float_ldpi 等来组织不同环境下的资源。系统根据当前设备的语言、主题、屏幕密度等配置自动选择匹配的资源文件。开发者只需在代码中使用 $r(‘app.string.key’) 引用资源无需关心当前环境。base 目录是默认资源目录当更具体的限定词目录没有匹配内容时系统会回退到 base。例如如果用户的语言是法语但应用没有提供 fr 限定词目录系统会自动使用 base 中的默认资源。解读资源限定词机制极大简化了国际化适配工作。开发者只需将翻译后的资源放入对应语言目录系统会自动匹配。base 作为兜底目录确保在任何环境下都有资源可用。习题 7简答题题目简述在 HarmonyOS 中实现多设备适配的核心方法以及 GridRow 栅格布局在其中的作用。答案多设备适配的核心方法包括使用断点系统sm/md/lg根据设备宽度切换布局使用 GridRow GridCol 栅格布局实现内容的自适应排列使用 vp/fp 单位替代 px 确保不同密度屏幕下尺寸一致使用 ohos.mediaquery 监听窗口尺寸变化动态调整使用 Navigation 的自适应模式自动切换单栏/分栏布局。GridRow 栅格布局的作用是为布局提供规律性的结构通过 columns 属性按断点设置不同列数通过 gutter 设置栅格间距通过 breakpoints 自定义断点位置。GridCol 的 span 属性支持按断点设置子组件占用的列数实现同一套代码在不同设备上呈现最优布局。解读多设备适配的关键在于“一次开发多端部署”。GridRow 栅格布局为响应式设计提供了标准化的结构配合断点系统和媒体查询开发者可以用一套代码适配手机、平板、折叠屏、PC 等多种设备形态。六、本节知识点总结资源管理与多语言通过资源限定词目录base、zh_CN、en_US、dark 等组织不同环境下的资源系统自动匹配并回退到 base。使用 $r(‘app.string.key’) 引用资源资源名在所有语言目录中保持一致。资源键应使用语义化命名避免 text1 等无意义名称。复数与区域化格式复数资源使用 plural.json 定义按数量选择文案。日期、数字、货币使用 ohos.intl 的 DateTimeFormat、NumberFormat 进行区域化格式化避免硬编码格式。无障碍适配屏幕朗读核心属性包括 accessibilityText无障碍文本优先级高于显示文本、accessibilityGroup合并子组件为一个焦点单元、accessibilityDescription操作后果说明、accessibilityLevel控制是否可被识别。文本类控件优先使用显示文本非文本类控件必须设置无障碍文本装饰性元素设置 accessibilityLevel(‘no’)。RTL 镜像布局当组件 direction 设置为 Direction.Rtl 或 Direction.Auto 且系统语言为 RTL 时镜像生效。使用 start / end 替代 left / right使用 LengthMetrics 类型。Canvas 不自动镜像需手动处理。方向性图标需单独提供 RTL 版本。多设备适配使用断点系统sm/md/lg和 GridRow GridCol 栅格布局实现响应式设计。尺寸单位使用 vp/fp配合 mediaquery 监听窗口变化。GridRow 通过 columns 按断点设置列数GridCol 通过 span 按断点控制子组件占用列数。下节预告第18课将进入 ArkUI 应用性能优化进阶的学习涵盖启动优化、渲染优化、内存优化与包体积优化的实战方法论与工具链使用。