鸿蒙中 requestFocus组件的焦点
自定义上下左右及 Tab 键的下一个焦点目标参数forwardbackwardupdownleftright优先级高于默认走焦规则。
本文同步发表于微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新
一、核心机制
-
焦点:指向当前界面唯一可交互元素的逻辑指针
-
应用场景:适用于电视、车机、可穿戴设备等非指向性输入场景,支持键盘、遥控器、旋钮等设备
-
焦点链机制:从根节点到获焦组件的整条路径上所有节点均处于“获焦状态”,形成一条视觉与逻辑统一的链式结构
2. 走焦行为
-
定义:焦点在组件间的转移过程,对用户透明
-
事件监听:可通过
onFocus和onBlur捕获焦点变化 -
走焦规范:详见华为开发者文档中的走焦规则部分
二、焦点激活态
1. 显示与隐藏逻辑
-
默认状态:隐藏
-
激活条件:应用必须处于“激活态”
-
重要关系:
-
获焦 ≠ 显示激活态(需应用激活)
-
显示激活态 → 该组件一定获焦
-
2. 激活与退出方式
| 方式 | 触发条件 | 备注 |
|---|---|---|
| 进入激活态 | 1. 按下 Tab 键(首次) 2. FocusController.activate(true) |
首次 Tab 仅激活,不走焦 |
| 退出激活态 | 1. FocusController.activate(false)2. 点击事件(触屏/鼠标) |
点击事件包括 onClick 和 Tap |
3. 样式系统
-
默认样式:组件内置焦点框
-
自定义接口:
focusBox()支持设置边距、颜色、粗细等 -
优先级规则:多个组件获焦时,优先显示子组件激活态,且只显示一个
三、层级页面
1. 定义与成员
-
包含组件:Page、Dialog、SheetPage、ModalPage、Menu、Popup、NavBar、NavDestination 等
-
视觉特性:独立层级,悬浮于其他内容之上
2. 三大核心特性
-
视觉层级独立:形成视觉上的叠加效果
-
焦点抢占:首次展示时立即抢占应用焦点
-
走焦范围限制:焦点无法通过按键移出该组件(NavBar、NavDestination 除外)
3. 特殊说明
-
Popup:
focusable为 false 时不抢占焦点 -
NavBar/NavDestination:走焦范围与首个父层级页面相同
4. 根容器机制
-
层级页面内的根节点,默认焦点位置
-
可通过
defaultFocus属性自定义默认焦点 -
首次 Tab 键:激活 + 传递焦点
四、焦点传递规则
1. 传递过程
-
从根节点开始,递归向下传递至第一个子组件
-
传递路径上的所有组件均处于获焦状态
-
直至叶子节点停止
2. 示例说明
-
点击 Button1 请求焦点给 Row 组件 → Row 的第一个可获焦子节点 Button2 获焦
-
形成焦点链:根 → Column → Row → Button2
五、走焦规范
1. 主动走焦
| 类型 | 触发方式 | 规则说明 |
|---|---|---|
| 按键走焦 | Tab/Shift+Tab/方向键 | 需应用处于激活态,范围限于当前层级页面 |
| requestFocus | 主动调用接口 | 可跨层级页面,不可跨窗口/ArkUI实例 |
| clearFocus | 清除焦点接口 | 焦点回到层级页面根容器 |
| focusOnTouch | 点击组件获焦 | 仅对可获焦组件有效,容器则传递给子组件 |
按键走焦:
-
Tab 键:Z 字型遍历所有叶子节点,循环走焦
-
Shift+Tab:反向遍历
-
方向键:十字型移动,采用中心点距离优先算法
-
子组件优先:子组件处理按键事件后,父组件不再介入
2. 被动走焦(系统自动触发)
| 触发场景 | 焦点转移规则 |
|---|---|
| 组件删除 | 尝试相邻兄弟组件(先向后,再向前) |
| 属性变更 | focusable/enabled 为 false 或 visibility 不可见 |
| 层级页面切换 | 旧页面释放焦点,新页面可能自动获焦 |
| Web组件初始化 | 组件自身逻辑触发,不属于框架规范 |
六、走焦算法
1. 线性走焦算法(默认)
-
适用容器:Row、Column、Flex(单方向布局)
-
核心规则:
-
按子节点挂载顺序走焦,与布局位置无关
-
Tab 键:顺序遍历
-
方向键:仅支持与容器方向平行的按键(Row 仅左右,Column 仅上下)
-
边界处理:首尾节点拒绝相反方向的方向键请求
-
2. 投影走焦算法
-
适用容器:配置了
wrap属性的 Flex 组件 -
核心规则:
-
方向键走焦:计算当前组件在方向上的投影与子组件的重叠面积
-
选择重叠面积非零且中心点距离最近的子组件
-
Tab 键:模拟方向右 + 下移高度后方向左判定
-
Shift+Tab:模拟方向左 + 上移高度后方向右判定
-
-
注意事项:组件大小不一、存在交叠时可能导致走焦顺序不符预期
3. 自定义走焦算法
-
由组件自定义实现,规格由组件定义
七、事件与状态管理
1. 获焦/失焦事件
-
onFocus:组件获焦时触发 -
onBlur:组件失焦时触发 -
通常成对使用,监听焦点变化
2. 事件响应顺序
-
父子节点同时监听时:
父节点失焦 → 子节点失焦 → 新子节点获焦 → 新父节点获焦
3. 组件获焦性控制
| 属性 | 作用 | 示例组件 |
|---|---|---|
focusable |
设置是否可获焦 | Text、Image 需设为 true |
enabled |
设为 false 时不可交互且不可获焦 | 所有交互组件 |
visibility |
None/Hidden 时不可见且不可获焦 | 所有组件 |
focusOnTouch |
点击后是否获焦 | 需要点击获焦的组件 |
4. 容器获焦特殊规则
-
叶子容器(无子组件的容器)默认不可获焦
-
使其可获焦的方法:
-
添加可获焦子组件(如 Button)
-
配置
onClick或Tap手势
-
-
焦点框绘制前提:
-
容器无获焦子节点
-
配置了
onClick或Tap手势 -
focusable属性设置正确
-
八、焦点控制
1. 焦点停留(tabStop)
-
设置容器在走焦时是否停留
-
停留后按 Enter 键,焦点进入容器内的第一个可获焦节点
2. 默认焦点(defaultFocus)
-
设置层级页面首次展示时的默认获焦组件
-
未设置时,焦点停留在根容器
3. 焦点优先级系统
-
focusScopeId:标识容器,可设置为焦点组 -
focusScopePriority:设置组件在容器内的获焦优先级 -
优先级等级:HIGH、PRIOR、PREVIOUS、LOW 等
4. 焦点组特性
-
快速走焦:Tab 键在焦点组间快速跳转
-
方向键限制:可通过
arrowStepOut控制是否允许方向键走出焦点组 -
TextInput 特殊:方向键无法直接走出 TextInput 组件
九、自定义走焦顺序
1. nextFocus(API 18+)
-
自定义上下左右及 Tab 键的下一个焦点目标
-
参数:
forward、backward、up、down、left、right -
优先级高于默认走焦规则
2. tabIndex
-
自定义 Tab 键走焦顺序
-
规则:
-
只遍历
tabIndex > 0的组件,按值从小到大循环 -
所有组件
tabIndex ≤ 0时,按默认规则走焦
-
-
限制:不能与
focusScopeId同时使用
十、焦点与按键事件交互
1. 按键触发点击事件
-
触发键:Enter、Space
-
适用事件:
onClick、TapGesture -
事件行为:
-
点击事件不冒泡(父组件不触发)
-
onKeyEvent默认冒泡 -
两者共存时均响应
-
2. 焦点与激活态关系
-
获焦组件响应点击事件,与是否显示激活态无关
十一、样式处理
1. 焦点框定制
-
focusBox()接口支持:-
margin:边距(LengthMetrics) -
strokeColor:边框颜色(ColorMetrics) -
strokeWidth:边框粗细
-
-
导入模块:
@kit.ArkUI中的ColorMetrics和LengthMetrics
2. 层级提升机制
-
绘制焦点激活态时,组件
zIndex默认提升至INT_MAX -
若组件已设置
zIndex,则保持不变 -
失焦或退出激活态时恢复原层级
十二、主动获焦/失焦接口对比
1. FocusController(推荐)
| 方法 | 作用 | 生效时间 | 优势 |
|---|---|---|---|
requestFocus(key) |
转移焦点至指定 id 组件 | 当帧生效 | 有异常值返回,避免多实例错误 |
clearFocus() |
清除焦点至根容器 | 当帧生效 | 强制清除,便于重置焦点状态 |
2. focusControl(旧版)
-
requestFocus(key):下一帧生效 -
可能存在多实例取错问题
十三、获焦组件
1. 基础组件分类
| 类型 | 示例 | 默认获焦 | 说明 |
|---|---|---|---|
| 默认可获焦 | Button、TextInput、Checkbox | true | 交互类组件 |
| 默认不可获焦 | Text、Image、DataPanel | false | 需显式设置 focusable(true) |
| 无获焦能力 | Blank、Span、ImageSpan | false | 设置无效 |
2. 容器组件
-
大多数可获焦:Column、Row、Flex、Grid、List、Scroll 等
-
少数不可获焦:Badge、EmbeddedComponent、RelativeContainer 等
3. 媒体组件
-
Video:可获焦,
focusable默认为 true
更多推荐



所有评论(0)