本文同步发表于微信公众号,微信搜索 程语新视界 即可关注,每个工作日都有文章更新

一、核心机制

  • 焦点:指向当前界面唯一可交互元素的逻辑指针

  • 应用场景:适用于电视、车机、可穿戴设备等非指向性输入场景,支持键盘、遥控器、旋钮等设备

  • 焦点链机制:从根节点到获焦组件的整条路径上所有节点均处于“获焦状态”,形成一条视觉与逻辑统一的链式结构

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. 三大核心特性

  1. 视觉层级独立:形成视觉上的叠加效果

  2. 焦点抢占:首次展示时立即抢占应用焦点

  3. 走焦范围限制:焦点无法通过按键移出该组件(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 组件

  • 核心规则

    1. 方向键走焦:计算当前组件在方向上的投影与子组件的重叠面积

    2. 选择重叠面积非零且中心点距离最近的子组件

    3. Tab 键:模拟方向右 + 下移高度后方向左判定

    4. Shift+Tab:模拟方向左 + 上移高度后方向右判定

  • 注意事项:组件大小不一、存在交叠时可能导致走焦顺序不符预期

3. 自定义走焦算法

  • 由组件自定义实现,规格由组件定义

七、事件与状态管理

1. 获焦/失焦事件

  • onFocus:组件获焦时触发

  • onBlur:组件失焦时触发

  • 通常成对使用,监听焦点变化

2. 事件响应顺序

  • 父子节点同时监听时:

父节点失焦 → 子节点失焦 → 新子节点获焦 → 新父节点获焦

3. 组件获焦性控制

属性 作用 示例组件
focusable 设置是否可获焦 Text、Image 需设为 true
enabled 设为 false 时不可交互且不可获焦 所有交互组件
visibility None/Hidden 时不可见且不可获焦 所有组件
focusOnTouch 点击后是否获焦 需要点击获焦的组件

4. 容器获焦特殊规则

  • 叶子容器(无子组件的容器)默认不可获焦

  • 使其可获焦的方法

    1. 添加可获焦子组件(如 Button)

    2. 配置 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 键的下一个焦点目标

  • 参数forwardbackwardupdownleftright

  • 优先级高于默认走焦规则

2. tabIndex

  • 自定义 Tab 键走焦顺序

  • 规则

    • 只遍历 tabIndex > 0 的组件,按值从小到大循环

    • 所有组件 tabIndex ≤ 0 时,按默认规则走焦

  • 限制:不能与 focusScopeId 同时使用

十、焦点与按键事件交互

1. 按键触发点击事件

  • 触发键:Enter、Space

  • 适用事件onClickTapGesture

  • 事件行为

    • 点击事件不冒泡(父组件不触发)

    • 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

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐