☰
仓颉 ArkUI 焦点事件开发指南:焦点链、走焦算法与 onFocus/onBlur 实战
2026/10/15 1:52:34 网站建设 项目流程
  • 文档
  • 知识库
  • 教程
  • OpenHarmony

【免费下载链接】CangjieCorpus

本仓库为仓颉编程语言语料库,聚焦 仓颉编程语言 核心知识体系,整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源,经结构化处理与专业标注,构建为支持 RAG(检索增强生成)技术 的高质量知识基座,适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用,推动鸿蒙开发生态智能化升级!

项目地址:https://gitcode.com/Cangjie/CangjieCorpus
点击查看免费下载

本篇指南完整讲解鸿蒙 ArkUI 中基于仓颉语言的焦点(Focus)事件体系:从"焦点、焦点链、走焦、焦点态"等基础概念入手,系统梳理主动走焦与被动走焦的触发机制、三种走焦算法(线性/投影/自定义)的运行规则,并给出onFocus/onBlur获焦失焦监听、focusable/focusOnTouch/defaultFocus等属性配置以及FocusControl.requestFocus主动申请焦点的完整可运行代码示例。读完本文,你将掌握为电视遥控器、键盘、车机摇杆等非指向性输入设备设计可键盘导航 UI 的完整方法,并能通过组件获焦能力表快速判断各基础/容器/媒体组件的可获焦性。

一、基础概念:焦点、焦点链与走焦

1. 焦点(Focus)

焦点指向当前应用界面上唯一的一个可交互元素。当用户使用键盘、电视遥控器、车机摇杆/旋钮等非指向性输入设备与应用程序进行间接交互时,基于焦点的导航和交互是最重要的输入手段。与触摸屏直接点按不同,非指向性设备无法直接告知系统"用户想操作哪个控件",因此系统必须维护一个唯一的"当前位置"——即焦点。

2. 焦点链(Focus Chain)

在应用的组件树形结构中,当一个组件获得焦点时,从根节点到该组件节点的整条路径上的所有节点都会被视为处于焦点状态,形成一条连续的焦点链。也就是说,焦点并非孤立存在于某个叶子组件上,而是沿组件树形成一条"链路":父容器连同其子孙获焦组件共同构成焦点链,焦点链的叶节点才是真正承载交互的组件。

3. 走焦(Focus Movement)

走焦指焦点在应用内组件之间转移的行为。这一过程对用户是透明的,但开发者可以通过监听onFocus(焦点获取)和onBlur(焦点失去)事件来捕捉这些变化。走焦的具体方式和规则见下文"走焦规范"。

二、焦点态(Focus State)

焦点态是用来指向当前获焦组件的样式。理解焦点态需要掌握以下几点规则:

  • 显示规则:默认情况下焦点态不会显示,只有当应用进入激活态后,焦点态才会显示。因此,虽然获得焦点的组件不一定显示焦点态(取决于是否处于激活态),但显示焦点态的组件必然是获得焦点的。
  • 自定义样式:大部分组件内置了焦点态样式,开发者同样可以使用样式接口自定义;一旦自定义,组件将不再显示内置的焦点态样式。
  • 多焦点态共存策略:在焦点链中,若多个组件同时拥有焦点态,系统采用子组件优先策略,优先显示子组件的焦点态,并且仅显示一个焦点态。

进入与退出激活态

场景触发方式说明
进入激活态外接键盘按下 TAB 键 / 调用FocusController.activate(true)方法进入激活态后,才可以使用键盘 TAB 键/方向键进行走焦;首次用来激活焦点态的 TAB 键不会触发走焦
退出激活态调用FocusController.active(false)方法 / 收到点击事件(包括手指触屏按下事件和鼠标左键按下事件)焦点激活态随即退出

三、层级页面与根容器

1. 层级页面(Page-Level Container)

层级页面是焦点框架中特定容器组件的统称,涵盖Page、Dialog、SheetPage、ModalPage、Menu、Popup、NavBar、NavDestination等。这些组件通常具有以下关键特性:

  1. 视觉层级独立性:从视觉呈现看,这些组件独立于其他页面内容,并通常位于其上方,形成视觉上的层级差异。
  2. 焦点跟随:此类组件在首次创建并展示之后,会立即将应用内焦点抢占。
  3. 走焦范围限制:当焦点位于这些组件内部时,用户无法通过键盘按键将焦点转移到组件外部的其他元素上,焦点移动仅限于组件内部。

在一个应用程序中,任何时候都至少存在一个层级页面组件,且该组件持有当前焦点。当该层级页面关闭或不再可见时,焦点会自动转移到下一个可用的层级页面组件上,确保用户交互的连贯性和一致性。

说明(例外情况):

  • Popup 组件 在focusable属性(组件属性,非通用属性)为false时,不具有第 2 条特性(焦点跟随)。
  • NavBar、NavDestination 不具有第 3 条特性(走焦范围限制),它们的走焦范围与其首个父层级页面相同。

2. 根容器(Root Container)

根容器是层级页面内的概念。当某个层级页面首次创建并展示时,根据层级页面的"焦点跟随"特性,焦点会立即被该页面抢占。此时,该层级页面所在焦点链的末端节点将成为默认焦点,而这个默认焦点通常位于该层级页面的根容器上。

  • 在缺省状态下,层级页面的默认焦点位于其根容器上,但开发者可以通过defaultFocus属性自定义这一行为。
  • 当焦点位于根容器时,首次按下 TAB 键不仅会使焦点进入激活状态,还会触发焦点向子组件的传递;如果子组件本身也是容器,则焦点会继续向下传递,直至到达叶子节点。
  • 传递规则:优先传递给上一次获得焦点的子节点;如果不存在这样的节点,则默认传递给第一个子节点。

四、走焦规范:主动走焦与被动走焦

根据走焦的触发方式,可以分为主动走焦和被动走焦两大类。

1. 主动走焦

指开发者/用户主观行为导致的焦点移动,包括:使用外接键盘的按键走焦(TAB 键/Shift+TAB 键/方向键)、使用requestFocus申请焦点、focusOnTouch点击申请焦点等接口导致的焦点转移。

(1)按键走焦
  • 前提:当前应用需处于焦点激活态。
  • 范围限制:按键走焦仅在当前获得焦点的层级页面内进行(参见上文"走焦范围限制")。
  • 按键类型与规则:
按键规则
TAB 键遵循Z 字型遍历逻辑,完成当前范围内所有叶子节点的遍历;到达当前范围内最后一个组件后,继续按下 TAB 键,焦点将循环至范围内第一个可获焦组件,实现循环走焦
Shift+TAB 键与 TAB 键具有相反的焦点转移效果
方向键(上、下、左、右)遵循十字型移动策略;在单层容器中,焦点转移由该容器的特定走焦算法决定;若算法判定下一个焦点应落在某个容器组件上,系统将采用中心点距离优先的算法进一步确定容器内的目标子节点
  • 走焦算法:每个可获焦的容器组件都有其特定的走焦算法,用于定义焦点转移的规则(详见下文"走焦算法")。
  • 子组件优先:当子组件处理按键走焦事件时,父组件将不再介入。
(2)requestFocus

requestFocus可以主动将焦点转移到指定组件上(详见下文"主动获焦/失焦")。其边界约束为:不可跨窗口、不可跨 ArkUI 实例申请焦点,但可以跨层级页面申请焦点。

(3)focusOnTouch

focusOnTouch使绑定组件具备点击后获得焦点的能力。注意:若组件本身不可获焦,则此功能无效;若绑定的是容器组件,点击后优先将焦点转移给上一次获焦的子组件,否则转移给第一个可获焦的子组件。

2. 被动走焦

被动走焦是指组件焦点因系统或其他操作而自动转移,无需开发者直接干预,这是焦点系统的默认行为。目前会被动走焦的机制有:

触发场景焦点处理逻辑
组件删除当处于焦点状态的组件被删除时,焦点框架首先尝试将焦点转移到相邻的兄弟组件上,遵循先向后、再向前的顺序;若所有兄弟组件均不可获焦,则焦点释放,并通知其父组件进行焦点处理
属性变更若将处于焦点状态的组件的focusable或enabled属性设置为false,或将visibility属性设置为不可见,焦点框架将自动转移焦点至其他可获焦组件(同样遵循先向后、再向前的兄弟遍历顺序)
层级页面切换当发生层级页面切换(如从一个页面跳转到另一个页面)时,当前页面的焦点将自动释放,新页面可能会根据预设逻辑自动获得焦点
Web 组件初始化对于 Web 组件,当其被创建时,若其设计需要立即获得焦点(如某些弹出框或输入框),则可能触发焦点转移至该 Web 组件;其行为属于组件自身的行为逻辑,不属于焦点框架的规格范围

五、走焦算法:线性、投影与自定义

在焦点管理系统中,每个可获焦的容器都配备有特定的走焦算法,这些算法定义了当使用 TAB 键、Shift+TAB 键或方向键时,焦点如何从当前获焦的子组件转移到下一个可获焦的子组件。

容器采用何种走焦算法取决于其UX(用户体验)规格,并由容器组件进行适配。目前,焦点框架支持三种走焦算法:线性走焦、投影走焦和自定义走焦。

1. 线性走焦算法

线性走焦算法是默认的走焦策略,它基于容器中子节点在节点树中的挂载顺序进行走焦,常用于单方向布局的容器,如 Row、Column 和 Flex 容器。运行规则如下:

  • 顺序依赖:走焦顺序完全基于子节点在节点树中的挂载顺序,与它们在界面上的实际布局位置无关。
  • TAB 键走焦:使用 TAB 键时,焦点将按照子节点的挂载顺序依次遍历。
  • 方向键走焦:当使用与容器定义方向垂直的方向键时,容器不接受该方向的走焦请求。例如,在横向的 Row 容器中,无法使用方向键进行上下移动。
  • 边界处理:当焦点位于容器的首尾子节点时,容器将拒绝与当前焦点方向相反的方向键走焦请求。例如,焦点在一个横向 Row 容器的第一个子节点上时,该容器无法处理方向键"左"的走焦请求。

2. 投影走焦算法

投影走焦算法基于当前获焦组件在走焦方向上的投影,结合子组件与投影的重叠面积和中心点距离进行胜出判定。该算法特别适用于子组件大小不一的容器,目前仅有配置了wrap属性的 Flex 组件。运行规则如下:

  • 规则 1(方向键走焦):判断投影与子组件区域的重叠面积,在所有面积不为 0 的子组件中,计算它们与当前获焦组件的中心点直线距离,距离最短者胜出;若存在多个备选,则节点树上更靠前的胜出。若无任何子组件与投影有重叠,说明该容器已无法处理该方向键的走焦请求。
  • 规则 2(TAB 键走焦):先按规则 1 以"方向键右"进行判定,找到则成功退出;若无法找到,则将当前获焦子组件的位置模拟向下移动该子组件的高度,再按"方向键左"进行投影判定,有投影重叠且中心点直线距离最远的子组件胜出;若无投影重叠的子组件,则表示该容器无法处理本次 TAB 键走焦请求。
  • 规则 3(Shift+TAB 键走焦):先按规则 1 以"方向键左"进行判定,找到则成功退出;若无法找到,则将当前获焦子组件的位置模拟向上移动该子组件的高度,再按"方向键右"进行投影判定,有投影重叠且中心点直线距离最远的子组件胜出;若无投影重叠的子组件,则表示该容器无法处理本次 Shift+TAB 键走焦请求。

3. 自定义走焦算法

由组件自定义的走焦算法,规格由组件自身定义(当前文档未展开其内部实现细节)。

六、获焦/失焦事件:onFocus 与 onBlur

1. 接口签名

public func onFocus(event: ?() -> Unit): T

获焦事件回调,绑定该接口的组件获焦时回调响应。

public func onBlur(event: ?() -> Unit): T

失焦事件回调,绑定该接口的组件失焦时回调响应。

onFocus和onBlur两个接口通常成对使用,用于监听组件的焦点变化。依据参考文档 焦点事件参考 的说明,这两个事件起始版本为 22,属于SystemCapability.ArkUI.ArkUI.Full系统能力,参数event为无参回调?() -> Unit,返回值T为通用方法接口类型,便于链式调用。

2. 完整示例:三按钮获焦变色

以下示例使用外接键盘的上下键让焦点在三个按钮间移动,按钮获焦时背景变绿、失焦时恢复灰色:

package ohos_app_cangjie_entry import kit.ArkUI.* import ohos.arkui.state_macro_manage.* @Entry @Component class EntryView { @State var oneButtonColor: Color = Color.Gray @State var twoButtonColor: Color = Color.Gray @State var threeButtonColor: Color = Color.Gray func build() { Column(space: 20) { // 通过外接键盘的上下键可以让焦点在三个按钮间移动,按钮获焦时颜色变化,失焦时变回原背景色 Button("First Button") .backgroundColor(oneButtonColor) .width(260) .height(70) .fontColor(Color.Black) // 监听第一个组件的获焦事件,获焦后改变颜色 .onFocus({ => oneButtonColor = Color.Green }) // 监听第一个组件的失焦事件,失焦后改变颜色 .onBlur({=> oneButtonColor = Color.Gray }) Button("Second Button") .backgroundColor(twoButtonColor) .width(260) .height(70) .fontColor(Color.Black) // 监听第二个组件的获焦事件,获焦后改变颜色 .onFocus({=> twoButtonColor = Color.Green }) // 监听第二个组件的失焦事件,失焦后改变颜色 .onBlur({=> twoButtonColor = Color.Gray }) Button("Third Button") .backgroundColor(threeButtonColor) .width(260) .height(70) .fontColor(Color.Black) // 监听第三个组件的获焦事件,获焦后改变颜色 .onFocus({=> threeButtonColor = Color.Green }) // 监听第三个组件的失焦事件,失焦后改变颜色 .onBlur({=> threeButtonColor = Color.Gray }) }.width(100.percent).margin(top: 20) } }

示例运行包含以下 3 步:

  1. 应用打开,按下 TAB 键激活走焦,"First Button"显示焦点态样式(组件外围出现一个蓝色闭合框),onFocus回调响应,背景色变成绿色。
  2. 按下 TAB 键,触发走焦,"Second Button"获焦,onFocus回调响应,背景色变成绿色;"First Button"失焦,onBlur回调响应,背景色变回灰色。
  3. 按下 TAB 键,触发走焦,"Third Button"获焦,onFocus回调响应,背景色变成绿色;"Second Button"失焦,onBlur回调响应,背景色变回灰色。

七、设置组件是否可获焦

1. 核心接口

public func focusable(value: ?Bool): T

设置组件是否可获焦。依据 焦点控制属性参考,value为?Bool类型,true表示组件可以获焦、false表示不可获焦,初始值为 true,系统能力为SystemCapability.ArkUI.ArkUI.Full,起始版本 22。

public func enabled(value: ?Bool): T

设置组件可交互性属性enabled为false,则组件不可交互、无法获焦(详见 enabled 属性参考)。

public func visibility(value: ?Bool): T

设置组件可见性属性visibility为Visibility.None或Visibility.Hidden,则组件不可见、无法获焦(详见 visibility 属性参考)。

public func focusOnTouch(value: ?Bool): T

设置当前组件是否支持点击获焦能力。初始值为false,即默认不支持点击获焦。

说明:当某组件处于获焦状态时,将其focusable属性或enabled属性设置为false,会自动使该组件失焦,然后焦点按照上文"被动走焦"规范自动转移给其他组件。

2. 组件的三类获焦能力

按照组件的获焦能力可大致分为三类:

  • 默认可获焦的组件:通常是有交互行为的组件,例如 Button、Checkbox、TextInput 组件。此类组件无需设置任何属性,默认即可获焦。
  • 有获焦能力、但默认不可获焦的组件:典型的是 Text、Image 组件。此类组件缺省情况下无法获焦,若需要使其获焦,可使用通用属性focusable(true)使能。对于没有配置focusable属性、有获焦能力但默认不可获焦的组件,为其配置onClick或单指单击的TapGesture手势后,该组件会隐式地成为可获焦组件;如果其focusable属性被设置为false,即使配置了上述事件,该组件依然不可获焦。
  • 无获焦能力的组件:通常是无任何交互行为的展示类组件,例如 Blank、Circle 组件。此类组件即使使用focusable属性也无法使其可获焦。

3. 完整示例:Text 的 focusable / focusOnTouch / enabled 联动

以下示例演示了focusable、focusOnTouch、enabled三个属性对 Text 组件获焦能力的影响,并通过onKeyEvent按键事件动态切换属性:

package ohos_app_cangjie_entry import kit.ArkUI.* import ohos.arkui.state_macro_manage.* @Entry @Component class EntryView { @State var textFocusable: Bool = true @State var textEnabled: Bool = true @State var color1: Color = Color(0xFFFF00) @State var color2: Color = Color(0xFFFF00) @State var color3: Color = Color(0xFFFF00) func build() { Column(space: 5) { // 第一个Text组件未设置focusable属性,默认不可获焦 Text("Default Text") .borderColor(color1) .borderWidth(2) .width(300) .height(70) .onFocus({ => color1 = Color.Blue }) .onBlur({ => color1 = Color(0xFFFF00) }) Divider() // 第二个Text设置了focusable初始为true,focusableOnTouch为true Text("focusable: " + textFocusable.toString()) .borderColor(color2) .borderWidth(2) .width(300) .height(70) .focusable(textFocusable) .focusOnTouch(true) .onFocus({ => color2 = Color.Blue }) .onBlur({ => color2 = Color(0xFFFF00) }) // 第三个Text设置了focusable为true,enabled初始为true Text("enabled: " + textEnabled.toString()) .borderColor(color3) .borderWidth(2) .width(300) .height(70) .focusable(true) .enabled(textEnabled) .focusOnTouch(true) .onFocus({ => color3 = Color.Blue }) .onBlur({ => color3 = Color(0xFFFF00) }) Divider() Row() { Button("Button1") .width(140).height(70) Button("Button2") .width(160).height(70) } Divider() Button("Button3") .width(300).height(70) Divider() } .width(100.percent) .justifyContent(FlexAlign.Center) .onKeyEvent({ e => // 绑定onKeyEvent,在该Column组件获焦时,按下'F'键,可将第二个Text的focusable置反 if (e.keyCode == 2022 && e.keyType == KeyType.Down) { textFocusable = !textFocusable } // 绑定onKeyEvent,在该Column组件获焦时,按下'G'键,可将第三个Text的enabled置反 if (e.keyCode == 2023 && e.keyType == KeyType.Down) { textEnabled = !textEnabled } }) } }

示例运行包含以下步骤:

  1. 第一个 Text 组件没有设置focusable(true)属性,该 Text 组件无法获焦。
  2. 点击第二个 Text 组件,由于设置了focusOnTouch(true),第二个组件获焦。按下 TAB 键触发走焦,仍然是第二个 Text 组件获焦。按键盘F 键,触发onKeyEvent,focusable置为false,第二个 Text 组件变成不可获焦,焦点自动转移——焦点框架自动从 Text 组件寻找下一个可获焦组件,焦点转移到第三个 Text 组件上。
  3. 按键盘G 键,触发onKeyEvent,enabled置为false,第三个 Text 组件变成不可获焦,焦点自动转移,使焦点转移到 Row 容器上;容器中使用的是默认配置,会进一步转移到 Button1 上。

八、默认焦点(defaultFocus)

1. 页面的默认焦点

public func defaultFocus(value: ?Bool): T

设置当前组件是否为当前页面上的默认焦点。依据 焦点控制属性参考 的说明,该属性仅在初次创建的页面第一次进入时生效,初始值为false。与之配套的还有 groupDefaultFocus(设置当前组件是否为所在容器获焦时的默认焦点)与 tabIndex(自定义组件 TAB 键走焦能力,tabIndex > 0的组件按索引值从小到大循环走焦),均起始版本为 22。

以下示例为第三个 Button 设置默认焦点,进入页面后第三个按钮直接获焦显示为绿色:

package ohos_app_cangjie_entry import kit.ArkUI.* import ohos.arkui.state_macro_manage.* @Entry @Component class EntryView { @State var oneButtonColor: Color = Color.Gray @State var twoButtonColor: Color = Color.Gray @State var threeButtonColor: Color = Color.Gray func build() { Column(space: 20) { // 通过外接键盘的上下键可以让焦点在三个按钮间移动,按钮获焦时颜色变化,失焦时变回原背景色 Button("First Button") .width(260) .height(70) .backgroundColor(oneButtonColor) .fontColor(Color.Black) // 监听第一个组件的获焦事件,获焦后改变颜色 .onFocus({ => oneButtonColor = Color.Green }) // 监听第一个组件的失焦事件,失焦后改变颜色 .onBlur({ => oneButtonColor = Color.Gray }) Button("Second Button") .width(260) .height(70) .backgroundColor(twoButtonColor) .fontColor(Color.Black) // 监听第二个组件的获焦事件,获焦后改变颜色 .onFocus({ => twoButtonColor = Color.Green }) // 监听第二个组件的失焦事件,失焦后改变颜色 .onBlur({ => twoButtonColor = Color.Gray }) Button("Third Button") .width(260) .height(70) .backgroundColor(threeButtonColor) .fontColor(Color.Black) // 设置默认焦点 .defaultFocus(true) // 监听第三个组件的获焦事件,获焦后改变颜色 .onFocus({ => threeButtonColor = Color.Green }) // 监听第三个组件的失焦事件,失焦后改变颜色 .onBlur({ => threeButtonColor = Color.Gray }) } .width(100.percent) .margin(top: 20) } }

示例运行包含以下 2 步:

  • 在第三个 Button 组件上设置了defaultFocus(true),进入页面后第三个 Button 默认获焦,显示为绿色。
  • 按下 TAB 键,触发走焦,第三个 Button 正处于获焦状态,会出现焦点框。

2. 页面/容器整体获焦时的焦点链

整体获焦与非整体获焦
  • 整体获焦:页面/容器自身作为焦点链的叶节点获焦,获焦后再把焦点链叶节点转移到子孙组件。例如:页面切换、Navigation 组件中的路由切换、焦点组走焦、容器组件主动调用requestFocusById等。
  • 非整体获焦:某个组件作为焦点链叶节点获焦,导致其祖先节点跟着获焦。例如:TextInput 组件主动获取焦点、TAB 键在非焦点组场景下走焦等。
整体获焦的焦点链形成规则
  1. 页面首次获焦:
    • 焦点链叶节点为配置了defaultFocus的节点;
    • 未配置defaultFocus时,焦点停留在页面的根容器上。
  2. 页面非首次获焦:由上次获焦的节点获焦。
  3. 获焦链上存在配置了获焦优先级的组件和容器:
    • 容器内存在优先级大于PREVIOUS的组件,由优先级最高的组件获焦;
    • 容器内不存在优先级大于PREVIOUS的组件,由上次获焦的节点获焦(例如窗口失焦后重新获焦的场景)。

九、主动获焦/失焦:FocusControl.requestFocus

使用focusControl中的方法可以主动申请焦点:

public static func requestFocus(value: ?String): Bool

调用此接口可以主动让焦点转移至参数指定的组件上,焦点转移生效时间为下一个帧信号。依据 焦点控制属性参考 的说明:

  • 参数value为目标组件使用接口key(value: string)或id(value: string)绑定的字符串;
  • 返回值Bool表示是否成功给目标组件申请到焦点:若参数指向的目标组件存在且目标组件可获焦,则返回true,否则返回false;
  • 起始版本 22,系统能力SystemCapability.ArkUI.ArkUI.Full。

以下示例通过id()为两个按钮绑定标识,点击第三个按钮调用FocusControl.requestFocus("testButton2")将焦点主动转移到第二个按钮:

package ohos_app_cangjie_entry import kit.ArkUI.* import ohos.arkui.state_macro_manage.* @Entry @Component class EntryView { @State var btColor: UInt32 = 0x2787d9 @State var btColor2: UInt32 = 0x2787d9 func build() { Column(space: 20) { Column(space: 5) { Button("Button") .width(200) .height(70) .fontColor(Color.White) .focusOnTouch(true) .backgroundColor(0x2787d9) .onFocus({ => btColor = 0xd5d5d5 }) .onBlur({ => btColor = 0x2787d9 }) .id("testButton") Button("Button") .width(200) .height(70) .fontColor(Color.White) .focusOnTouch(true) .backgroundColor(btColor2) .onFocus({ => btColor2 = 0xd5d5d5 }) .onBlur({ => btColor2 = 0x2787d9 }) .id("testButton2") Divider() .vertical(false) .width(80.percent) .backgroundColor(0x707070) .height(10) //点击focusControl.requestFocus按钮,第二个Button获焦。 Button("FocusControl.requestFocus") .width(200) .height(70) .fontColor(Color.White) .onClick({ evt => FocusControl.requestFocus("testButton2") }) .backgroundColor(0xff2787d9) } } .width(100.percent) .height(100.percent) } }

十、焦点与按键事件的联动

当组件获焦**且存在点击事件(onClick)或单指单击事件(TapGesture)**时,回车键和空格键会触发对应的事件回调。相关行为规则如下:

说明:

  • 点击事件(onClick)或单指单击事件(TapGesture)在回车、空格触发对应事件回调时,默认不冒泡传递,即父组件对应的按键事件不会被同步触发。
  • 按键事件(onKeyEvent)默认冒泡传递,即同时会触发父组件的按键事件回调。
  • 组件同时存在点击事件(onClick)和按键事件(onKeyEvent)时,在回车、空格触发时,两者都会响应。
  • 获焦组件响应点击事件(onClick),与焦点激活态无关。

以下示例演示焦点与点击事件的联动:Button 获焦后,通过回车/空格即可触发其onClick回调,点击次数奇偶变化时按钮文本随之更新:

package ohos_app_cangjie_entry import kit.ArkUI.* import ohos.arkui.state_macro_manage.* @Entry @Component class EntryView { @State var count: Int = 0 @State var name: String = "Button" func build() { Column { Button(name) .fontSize(30) .onClick({ evt => count++ if (count <= 0) { name = "count is negative number" } else if (count % 2 == 0) { name = "count is even number" } else { name = "count is odd number" } }) .height(60) } .height(100.percent).width(100.percent).justifyContent(FlexAlign.Center) } }

十一、组件获焦能力总览

以下三张表汇总了基础组件、容器组件与媒体组件的获焦能力及focusable默认值,是判断"某个组件能否通过键盘聚焦、是否需要手动开启 focusable"的权威依据。各组件详细说明可点击链接进入对应参考文档。

1. 基础组件获焦能力

基础组件是否有获焦能力focusable 默认值
AlphabetIndexer是true
Blank否false
Button是true
Checkbox是true
CheckboxGroup是true
DataPanel是false
DatePicker是true
Divider是false
Gauge是false
Image是false
ImageSpan否false
LoadingProgress是true
Navigation是true
PatternLock是true
Progress是true
QRCode是true
Radio是true
Rating是true
RichEditor是true
RichText否false
ScrollBar否false
Search是true
Select是true
Slider是true
Span否false
Stepper是true
StepperItem是true
Text是false
TextArea否false
TextClock否false
TextInput是true
TextPicker是true
TextTimer否false
Toggle是true

2. 容器组件获焦能力

容器组件是否可获焦focusable 默认值
Badge否false
Column是true
Flex是true
GridCol是true
GridRow是true
Grid是true
GridItem是true
List是true
ListItem是true
ListItemGroup是true
Navigator是true
Refresh是true
RelativeContainer否false
Row是true
RowSplit是true
Scroll是true
SideBarContainer是true
Stack是true
Swiper是true
Tabs是true

3. 媒体组件获焦能力

媒体组件是否可获焦focusable 默认值
Video是true

4. 使用要点

  • 有获焦能力、默认不可获焦的组件(如 Text、Image、DataPanel、Divider、Gauge、Progress 等,focusable默认值为false):必须显式调用focusable(true)才可获焦并触发焦点事件。
  • 无获焦能力的组件(如 Blank、ImageSpan、RichText、ScrollBar、Span、TextArea、TextClock、TextTimer、Badge、RelativeContainer 等):即使设置focusable(true)也无法获焦。
  • 对于有获焦能力的容器组件(如 Stack、Row 等),若不存在可获焦的子组件,该容器组件不可获焦;为其配置onClick或单指单击的TapGesture手势后,该组件会隐式地成为可获焦组件(参见 焦点事件参考 中的说明)。
  • 依据焦点控制参考的补充说明:自定义组件无获焦能力,当设置focusable、enabled等属性为false,或设置visibility为Hidden、None时,不影响其子组件的获焦;组件主动获取焦点不受窗口焦点的控制。

十二、配套参考文档速查

在仓库中,本文涉及的焦点接口均有对应的参考文档可深入查阅:

  • 焦点事件参考:onFocus / onBlur 接口签名与参数说明
  • 焦点控制属性参考:defaultFocus / focusable / focusOnTouch / groupDefaultFocus / tabIndex / FocusControl.requestFocus
  • enabled 可交互性属性参考
  • visibility 可见性属性参考
  • 按键事件参考:onKeyEvent 与按键冒泡行为

按"焦点开发"实践路径,建议阅读顺序为:先读本文掌握概念与规范,再结合 焦点控制属性参考 与 焦点事件参考 核对每个接口的参数、默认值与系统能力约束,最后将上文示例中的代码段直接嵌入仓颉 ArkUI 工程(注意导入kit.ArkUI.*与ohos.arkui.state_macro_manage.*)进行验证,即可完整掌握鸿蒙 ArkUI 的焦点事件开发能力。

  • 文档
  • 知识库
  • 教程
  • OpenHarmony

【免费下载链接】CangjieCorpus

本仓库为仓颉编程语言语料库,聚焦 仓颉编程语言 核心知识体系,整合官方开发指南、API 文档、典型代码示例及语法规范等多维度资源,经结构化处理与专业标注,构建为支持 RAG(检索增强生成)技术 的高质量知识基座,适配智能编码助手、学习辅助工具等应用开发需求。 欢迎开发者基于本语料库构建仓颉语言智能应用,推动鸿蒙开发生态智能化升级!

项目地址:https://gitcode.com/Cangjie/CangjieCorpus
点击查看免费下载

相关推荐

上一篇:《Must-Reading on ISAC》开源项目使用教程
下一篇:VLOOK™ 终极入门指南:10分钟让你的Markdown文档焕然一新

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询