鸿蒙掌上驾考宝典应用开发35:字体缩放——无障碍适配实践
·
第35篇:字体缩放——无障碍适配实践

一、引言
无障碍适配是鸿蒙应用开发的重要课题,它关乎所有用户的使用体验,特别是视力不佳的用户群体。DriverLicenseExam 项目在 1.0.6 版本中新增了"答题字体跟随系统变化"功能,并在 1.0.7 版本中进一步优化了深色模式下的字体显示。本文将深入解析字体缩放功能的实现原理和最佳实践。
二、字体缩放的核心机制
2.1 系统字体缩放与 maxFontScale
在鸿蒙系统中,用户可以在"设置 → 显示和亮度 → 字体大小"中调整系统字体大小。应用需要响应这一变化,但有些场景需要限制最大缩放比例以避免布局溢出。
ArkUI 的 Text 组件提供了 maxFontScale 属性来控制字体最大缩放比例:
// 限制字体最大缩放比例为 1(不跟随系统缩放)
Text('广告标题')
.fontSize(20)
.maxFontScale(1); // 不随系统缩放
// 允许跟随系统缩放,但限制最大 1.2 倍
Text('顺序练习')
.fontSize(14)
.maxFontScale(1.2); // 最大缩放到 1.2 倍
// 不设置 maxFontScale,完全跟随系统
Text('题目内容')
.fontSize(16); // 会跟随系统缩放
2.2 项目中 maxFontScale 的使用场景
项目中有选择地使用了 maxFontScale:
// 场景1:广告文案 - 不允许缩放(保持设计效果)
Text('学好驾车,安全你我')
.fontSize(20)
.fontColor('#FFFFFF')
.maxFontScale(1); // 广告文字不缩放
// 场景2:功能按钮 - 允许适度缩放
Text('顺序练习')
.fontSize(14)
.fontColor('#FFFFFF')
.maxFontScale(1.2); // 最大 1.2 倍
// 场景3:统计数字 - 允许缩放但保持布局
Text('练习进度')
.fontSize(10)
.maxFontScale(1.5); // 小字可以放大更多
// 场景4:Tab 标签 - 不允许缩放
Text('首页')
.fontSize(14)
.maxFontScale(1); // 标签栏文字不缩放
三、字体大小滑块实现
3.1 自定义字体缩放
除了跟随系统字体,项目还提供了应用内的字体大小调节功能,让用户可以在应用内独立控制字体大小:
// FontSizeSlider.ets
@ComponentV2
export struct FontSizeSlider {
@Local fontSize: number = 1.0; // 1.0 = 100% 缩放
build() {
Column() {
// 标题
Text('字体大小').fontSize(16).maxFontScale(1);
// 预览文本
Text('驾考模拟练习')
.fontSize(Math.round(16 * this.fontSize))
.fontColor($r('sys.color.font_primary'))
.margin({ top: 16, bottom: 16 });
// 滑块
Slider({
value: this.fontSize,
min: 0.85, // 最小 85%
max: 1.15, // 最大 115%
step: 0.05, // 步长 5%
})
.showTips(true) // 显示当前值
.onChange((value: number) => {
this.fontSize = value;
FontUtils.setFontScale(value);
});
// 大小标签
Row() {
Text('小').fontSize(12).maxFontScale(1);
Blank();
Text('标准').fontSize(12).maxFontScale(1);
Blank();
Text('大').fontSize(12).maxFontScale(1);
}
.width('100%')
.margin({ top: 8 });
}
.padding(16)
.width('100%');
}
}
3.2 FontUtils 工具类
// FontUtils.ets
export class FontUtils {
private static scale: number = 1.0;
// 设置字体缩放比例
static setFontScale(scale: number) {
FontUtils.scale = scale;
// 保存到 Preferences
const preferencesUtil = PreferencesUtil.getInstance();
const preference = preferencesUtil.getPreferences(context);
preferencesUtil.preferencesPut(preference, 'fontScale', scale);
}
// 获取当前字体缩放
static getFontScale(): number {
return FontUtils.scale;
}
// 计算缩放后的字体大小
static calculateSize(baseSize: number): number {
return Math.round(baseSize * FontUtils.scale);
}
}
四、鸿蒙字体使用
4.1 系统字体
项目使用了鸿蒙系统字体,确保在不同设备上显示一致:
// 使用鸿蒙系统字体
.fontFamily('HarmonyOS Sans') // 英文字体
.fontFamily('鸿蒙黑体') // 中文字体
4.2 字体大小单位
项目使用 fp 作为字体大小单位,这是鸿蒙推荐的字体单位,会自动跟随系统字体缩放:
// font.json 中定义字体大小
{ "name": "font_size_10", "value": "10fp" }
{ "name": "font_size_14", "value": "14fp" }
{ "name": "font_size_16", "value": "16fp" }
{ "name": "font_size_24", "value": "24fp" }
4.3 代码中的字体引用
// 引用资源中定义的字体大小
.fontSize($r('app.string.font_size_10'))
.fontSize($r('app.string.font_size_14'))
.fontSize($r('app.string.font_size_24'))
// 直接指定字体大小(不推荐)
.fontSize(14)
推荐使用 $r 引用资源文件中的字体大小,便于统一管理。
五、字体适配的挑战与解决方案
5.1 布局溢出问题
当字体放大时,文本可能超出容器边界。项目通过多种方式解决:
// 方案1:限制最大行数 + 省略号
Text('题目内容')
.fontSize(16)
.maxLines(2) // 最多显示 2 行
.textOverflow({ overflow: TextOverflow.Ellipsis }); // 超出显示省略号
// 方案2:使用 maxFontScale 限制最大缩放
Text('重要标签')
.fontSize(14)
.maxFontScale(1.2); // 最大 1.2 倍
// 方案3:使用 minHeight 确保容器高度
Row() {
Text('设置项').fontSize(16);
}
.minHeight(46) // 最小高度保证触摸区域
.padding({ left: 12, right: 12 });
5.2 触摸区域适配
字体变大时,按钮的触摸区域也需要相应调整:
// 使用 minHeight 确保触摸区域
Button('提交')
.minHeight(44) // 最小触摸高度 44vp
.fontSize(16);
六、字体缩放在不同场景的应用分析
6.1 考试页面的字体适配
考试页面是文字内容最密集的场景,需要特别注意字体适配:
// 考试题目:允许较大缩放,但限制最大行数
Text(currentQuestion.question)
.fontSize(16)
.maxFontScale(1.5) // 允许放大到 1.5 倍
.lineHeight(24)
.maxLines(6) // 最多显示 6 行
.textOverflow({ overflow: TextOverflow.Ellipsis });
// 选项文本:跟随缩放,保证可读性
Text(optionText)
.fontSize(14)
.maxFontScale(1.5)
.padding({ left: 12, right: 12 });
// 题号/进度:小字可以放大更多
Text('第 ' + (currentIndex + 1) + ' / ' + total + ' 题')
.fontSize(12)
.maxFontScale(2.0); // 小字允许更大缩放比例
6.2 统计面板的字体适配
统计页面数字较大,需要平衡显示效果和缩放需求:
// 统计数字:大字号,限制缩放防止溢出
Text(String(this.didCount))
.fontSize(24)
.fontFamily('鸿蒙黑体')
.fontWeight(FontWeight.Medium)
.height(32)
.maxFontScale(1.2) // 大字号限制缩放
.textAlign(TextAlign.Center);
// 统计标签:允许正常缩放
Text('已做题')
.fontSize(14)
.fontFamily('鸿蒙黑体')
.maxFontScale(1.5);
6.3 底部 Tab 栏的字体适配
Tab 栏空间有限,需要严格限制缩放:
// Tab 标签:不允许缩放,保持布局稳定
Text(item.label)
.fontColor(this.vm.curIndex === index ?
$r('app.color.icon_color_highlight') : $r('sys.color.font_secondary'))
.fontSize($r('app.string.font_size_10'))
.maxFontScale(1); // 标签栏文字不缩放
七、无障碍适配最佳实践
6.1 无障碍检查清单
- 所有文本使用
fp单位 - 关键文本设置
maxFontScale限制 - 广告/装饰性文本设置
maxFontScale(1) - 按钮使用
minHeight保证触摸区域 - 容器使用
minHeight而非固定高度 - 文本超出时使用
textOverflow处理 - 图片使用
objectFit控制缩放
6.2 用户偏好持久化
// 字体缩放偏好持久化
aboutToAppear() {
const preferencesUtil = PreferencesUtil.getInstance();
const preference = preferencesUtil.getPreferences(context);
const savedScale = preferencesUtil.getPreferencesValue(preference, 'fontScale');
if (savedScale) {
FontUtils.setFontScale(Number(savedScale));
}
}
七、总结
字体缩放适配是鸿蒙应用无障碍设计的重要组成部分。DriverLicenseExam 项目通过以下方式实现了良好的字体适配:
- maxFontScale 控制:为不同场景设置不同的最大缩放比例
- 字体大小滑块:应用内独立调节字体大小
- fp 单位:使用鸿蒙推荐的字体单位
- 布局保护:通过 minHeight、maxLines 等属性防止布局溢出
- 偏好持久化:通过 Preferences 保存用户字体偏好
关键源码文件:
components/app_setting/src/main/ets/components/FontSizeSlider.ets— 字体大小滑块components/app_setting/src/main/ets/common/FontUtils.ets— 字体工具类AppScope/resources/base/element/font.json— 字体大小定义commons/commonLib/src/main/ets/utils/PreferencesUtil.ets— 偏好持久化
更多推荐





所有评论(0)