1# Focus Event 2 3## Basic Concepts and Specifications 4 5### Basic Concepts 6 7**Focus, Focus Chain, and Focus Traversal** 8 9- Focus: refers to the single interactive element on the current application screen. When users interact indirectly with the application using non-pointing input devices such as keyboards, TV remote controls, or in-car joysticks/knobs, navigation and interaction based on focus are crucial means of input. 10- Focus chain: refers to the sequence of nodes from the root to a focused component in the application's component tree, where all nodes are considered focused. 11- Focus traversal: refers to the behavior of focus shifting between components in an application. This process is transparent to the user but can be monitored through **onFocus** and **onBlur** events. For details on how focus traversal is managed, see [Focus Traversal Guidelines](#focus-traversal-guidelines) 12 13 14**Focus State** 15 16Refers to the style indicating the currently focused component. 17 18- Display rules: The focus state is not displayed by default; it only appears when the application is active. A component with the focus state is definitely focused, but not all focused components show the state, depending on the activation status. Most components come with default focus state styles; you customize these styles when needed. Once customized, the component will no longer display the default focus state style. In a focus chain, if multiple components have the focus state, the system shows the focus state for only one, prioritizing the child component's focus state over others. 19- Entering the activated state: Pressing the **Tab** key on an external keyboard or using the **activate(true)** API of **FocusController** activates focus, allowing subsequent use of the **Tab** key or arrow keys for focus traversal. The initial **Tab** press that activates focus does not cause focus to move. 20- Exiting the activated state: Focus activation ends when the application receives either the **activate(true)** API call from **FocusController** or any form of click event, such as touch screen presses or mouse clicks. 21 22 23**Hierarchical Pages** 24 25Hierarchical pages are specialized container components, such as **Page**, **Dialog**, **SheetPage**, **ModalPage**, **Menu**, **Popup**, **NavBar**, and **NavDestination**, within a focus framework. These components typically have the following key features: 26 27- Visual layering: They appear on top of other content, creating a distinct visual hierarchy. 28- Focus capture: They automatically take focus when first displayed. 29- Focus limitation: When focus is within these components, users cannot use keyboard keys to move focus outside to other elements. In other words, focus movement is confined within the component. 30 31An application always has at least one hierarchical page in focus. When this hierarchical page is closed or no longer visible, the focus shifts to another, ensuring smooth user interaction. 32 33> **NOTE** 34> 35> The **Popup** component does not capture focus if it has **focusable** set to **false**. 36> 37> The **NavBar** and **NavDestination** components do not restrict focus movement and share the focus scope of their immediate parent hierarchical page. 38 39**Root Container** 40 41In hierarchical pages, the root container is where the default focus resides when the page is first shown. 42 43You can change the default focus using the **defaultFocus** attribute. 44 45Pressing **Tab** with focus on the root container activates focus and passes it to child components. Focus proceeds to the last focused child or the first child if no previous focus exists, until it reaches the leaf node. 46 47 48 49### Focus Traversal Guidelines 50 51Focus traversal can be divided into active and passive based on how it is triggered. 52 53**Active Focus Traversal** 54 55 56Active focus traversal refers to focus movement initiated by deliberate actions, such as keyboard shortcuts (**Tab**, **Shift+Tab**, arrow keys) and programmatic focus control through **requestFocus**, **clearFocus**, and **focusOnTouch**. 57 58 59- Keyboard traversal 601. Prerequisite: The application is in the focus activated state. 612. Scope: limited to the currently focused hierarchical page, as detailed in the "Focus limitation" section under "Hierarchical Pages." 623. Key types: 63**Tab** key: follows a Z-shaped logic to traverse all leaf nodes within the scope, looping back to the first after the last. 64**Shift+Tab**: reverses the direction of the **Tab** key. 65Arrow keys (up, down, left, and right): moves focus in a cross-shaped pattern, with container-specific algorithms determining the next focus in a single-layer container. If the algorithm determines the next focus should be on a container component, the system uses a center-point distance priority algorithm to further identify the target child node within the container. 664. Traversal algorithm: Each focusable container has a unique algorithm defining how focus moves. 675. Priority: Child components take precedence in handling keyboard events over parents. 68 69- requestFocus 70Moves focus to a specific component, which is allowed across hierarchical pages but not across windows or different ArkUI instances. 71For details, see [Active Focus Acquisition/Loss](#active-focus-acquisitionloss). 72 73- clearFocus 74Clears the focus within the current hierarchical page, with the focus reverting to the root container. For details, see [clearFocus](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md#clearfocus12). 75 76- focusOnTouch 77Enables a component to gain focus on touch. It is ineffective on non-focusable components. For container components, focus goes to the last focused child or the first focusable child upon touch. For details, see [focusOnTouch](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md#focusontouch9). 78 79 80**Passive Focus Traversal** 81 82Passive focus traversal occurs when the focus automatically shifts due to system actions or other operations without developer intervention, reflecting the default behavior of the focus system. 83 84 85Mechanisms that trigger passive focus traversal include: 86 87- Component removal: If a focused component is removed, the system tries to shift focus to the next available sibling, following a back-to-front order. If no siblings are focusable, focus is released to the parent component. 88- Attribute change: Changing a component's **focusable** or **enabled** to **false**, or **visibility** to invisible causes the system to automatically move focus to another focusable component, using the same method as for component removal. 89- Hierarchical page transition: During switching between hierarchical pages, the current page's focus is automatically released, and the new page may automatically gain focus according to preset logic. 90- **Web** component initialization: The **Web** component may immediately gain focus upon creation if designed to do so (for example, certain dialog boxes or text boxes), which is part of the component's behavior and not governed by the focus framework specifications. 91 92 93 94### Focus Traversal Algorithms 95 96In the focus management system, every focusable container is assigned a specific algorithm that dictates how focus moves from the current to the next focusable child component when **Tab**, **Shift+Tab**, or arrow keys are used. 97 98The algorithm used by a container is based on its UX design and is implemented by the component itself. The focus framework supports three focus traversal algorithms: linear, projection, and custom. 99 100 101 102**Linear Focus Traversal Algorithm** 103 104 105The linear focus traversal algorithm is the default algorithm, focusing on the order of child nodes in the node tree, commonly used in single-direction layouts such as **Row**, **Column**, and **Flex** containers. Its operation rules are as follows: 106 107 108- Order dependency: The focus order is based solely on the mounting sequence of child nodes in the node tree, independent of their visual layout. 109- **Tab** key traversal: The **Tab** key moves focus through nodes in their mounting sequence. 110- Arrow key traversal: Arrow keys perpendicular to the container's layout direction are ignored. For example, a horizontal **Row** container does not accept focus requests from up and down keys. 111- Boundary handling: The container rejects focus requests in the opposite direction from the current focus edge. For example, if the focus is on the first child of a horizontal **Row** container, it won't process leftward focus requests. 112 113 114**Projection Focus Traversal Algorithm** 115 116The projection focus traversal algorithm determines the next focus based on the overlap area and center-point distance of the projection of the current focused component in the direction of focus movement. It is particularly suitable for containers with varying child sizes, such as the **Flex** component with the **wrap** attribute. Its operation rules are as follows: 117 118 119- Arrow keys: Focus goes to the child with the largest overlap area and the shortest center-point distance to the projection of the current focus. If multiple children qualify, the first in the node tree is chosen. If no components overlap with the projection, the focus request is unprocessable. 120- **Tab** key: It mimics a rightward shift to find the next focus; if none is available, it simulates moving the current focus down its height, and then checks leftward. The child farthest in the direction with overlapping projection wins. 121- **Shift+Tab** key: It mimics a leftward shift to find the next focus; if none is available, it simulates moving the current focus up its height, and then checks rightward. The child farthest in the direction with overlapping projection wins. 122 123 124**Custom Focus Traversal Algorithm** 125 126The custom focus traversal algorithm is defined by the component itself, allowing for specific focus traversal behaviors as determined by the component's design specifications. 127 128## onFocus/onBlur Events 129 130```ts 131onFocus(event: () => void) 132``` 133 134 135Triggered when the bound component obtains focus. 136 137```ts 138onBlur(event:() => void) 139``` 140 141Triggered when the bound component loses focus. 142 143The **onFocus** and **onBlur** APIs are usually used in pairs to listen for the focus changes of the component. 144 145```ts 146// xxx.ets 147@Entry 148@Component 149struct FocusEventExample { 150 @State oneButtonColor: Color = Color.Gray; 151 @State twoButtonColor: Color = Color.Gray; 152 @State threeButtonColor: Color = Color.Gray; 153 154 build() { 155 Column({ space: 20 }) { 156 // You can use the up and down arrow keys on an external keyboard to move the focus between the three buttons. When a button gains focus, its color changes. When it loses focus, its color changes back. 157 Button('First Button') 158 .width(260) 159 .height(70) 160 .backgroundColor(this.oneButtonColor) 161 .fontColor(Color.Black) 162 // Listen for the focus obtaining event of the first component and change its color when it obtains focus. 163 .onFocus(() => { 164 this.oneButtonColor = Color.Green; 165 }) 166 // Listen for the focus loss event of the first component and change its color when it loses focus. 167 .onBlur(() => { 168 this.oneButtonColor = Color.Gray; 169 }) 170 171 Button('Second Button') 172 .width(260) 173 .height(70) 174 .backgroundColor(this.twoButtonColor) 175 .fontColor(Color.Black) 176 // Listen for the focus obtaining event of the second component and change its color when it obtains focus. 177 .onFocus(() => { 178 this.twoButtonColor = Color.Green; 179 }) 180 // Listen for the focus loss event of the second component and change its color when it loses focus. 181 .onBlur(() => { 182 this.twoButtonColor = Color.Grey; 183 }) 184 185 Button('Third Button') 186 .width(260) 187 .height(70) 188 .backgroundColor(this.threeButtonColor) 189 .fontColor(Color.Black) 190 // Listen for the focus obtaining event of the third component and change its color when it obtains focus. 191 .onFocus(() => { 192 this.threeButtonColor = Color.Green; 193 }) 194 // Listen for the focus loss event of the third component and change its color when it loses focus. 195 .onBlur(() => { 196 this.threeButtonColor = Color.Gray ; 197 }) 198 }.width('100%').margin({ top: 20 }) 199 } 200} 201``` 202 203 204 205 206 207The preceding example includes three steps: 208 209- When the application is opened, pressing the **Tab** key activates focus traversal, **First Button** displays a focus state style – a blue bounding box around the component – and its **onFocus** callback is triggered, changing the background color to green. 210- When the **Tab** key is pressed again, **Second Button** gains focus, triggering its **onFocus** callbacktriggered, and its background color turns green, while **First Button** loses focus, triggering its **onBlur** callback, and its background color reverts to gray. 211- A subsequent **Tab** key press causes **Third Button** to gain focus, triggering its **onFocus** callback, and its background color turns green. Concurrently, **Second Button** loses focus, triggering its **onBlur** callback, and its background color reverts to gray. 212 213## Setting Whether a Component Is Focusable 214 215```ts 216focusable(value: boolean) 217``` 218 219Sets whether the component is focusable. 220 221Components can be classified into the following types based on their focusability: 222 223- Default focusable components: These components are usually interactive components, such as **Button**, **Checkbox**, and **TextInput**. 224 225- Focusable but default unfocusable components: Typical examples are **Text** and **Image**. To enable them to be focusable, use the **focusable(true)** attribute. When these components do not have the **focusable** attribute set, setting an **onClick** event or a single-tap gesture implicitly makes them focusable. However, when these components have the **focusable** attribute set to **false**, they remain unfocusable even if you bind the aforementioned event or gesture to them. 226 227- Non-focusable components: Components that do not allow for interactions, such as **Blank** and **Circle**, cannot be made focusable, even with the **focusable** attribute applied. 228 229 230```ts 231enabled(value: boolean) 232``` 233 234Sets the component's interactivity. If [enabled](../reference/apis-arkui/arkui-ts/ts-universal-attributes-enable.md#enabled) is set to **false**, the component becomes non-interactive and cannot gain focus. 235 236 237```ts 238visibility(value: Visibility) 239``` 240 241Sets the component's visibility. If [visibility](../reference/apis-arkui/arkui-ts/ts-universal-attributes-visibility.md#visibility) set to **Visibility.None** or **Visibility.Hidden**, the component becomes invisible and cannot gain focus. 242 243 244```ts 245focusOnTouch(value: boolean) 246``` 247 248Sets whether the component is focusable on touch. 249 250 251>**NOTE** 252> 253>- When a component that is currently focused has its **focusable** or **enabled** attribute set to **false**, it automatically loses focus. The focus then shifts to another component according to the [Focus Traversal Guidelines](#focus-traversal-guidelines). 254 255 256```ts 257// xxx.ets 258@Entry 259@Component 260struct FocusableExample { 261 @State textFocusable: boolean = true; 262 @State textEnabled: boolean = true; 263 @State color1: Color = Color.Yellow; 264 @State color2: Color = Color.Yellow; 265 @State color3: Color = Color.Yellow; 266 267 build() { 268 Column({ space: 5 }) { 269 Text('Default Text') // The first Text component does not have the focusable attribute set, and is not focusable by default. 270 .borderColor(this.color1) 271 .borderWidth(2) 272 .width(300) 273 .height(70) 274 .onFocus(() => { 275 this.color1 = Color.Blue; 276 }) 277 .onBlur(() => { 278 this.color1 = Color.Yellow; 279 }) 280 Divider() 281 282 Text('focusable: ' + this.textFocusable) // The second Text component initially has focusable set to true and focusOnTouch true. 283 .borderColor(this.color2) 284 .borderWidth(2) 285 .width(300) 286 .height(70) 287 .focusable(this.textFocusable) 288 .focusOnTouch(true) 289 .onFocus(() => { 290 this.color2 = Color.Blue; 291 }) 292 .onBlur(() => { 293 this.color2 = Color.Yellow; 294 }) 295 296 Text('enabled: ' + this.textEnabled) // The third Text component has focusable set to true, enabled initially true. 297 .borderColor(this.color3) 298 .borderWidth(2) 299 .width(300) 300 .height(70) 301 .focusable(true) 302 .enabled(this.textEnabled) 303 .focusOnTouch(true) 304 .onFocus(() => { 305 this.color3 = Color.Blue; 306 }) 307 .onBlur(() => { 308 this.color3 = Color.Yellow; 309 }) 310 311 Divider() 312 313 Row() { 314 Button('Button1') 315 .width(140).height(70) 316 Button('Button2') 317 .width(160).height(70) 318 } 319 320 Divider() 321 Button('Button3') 322 .width(300).height(70) 323 324 Divider() 325 }.width('100%').justifyContent(FlexAlign.Center) 326 .onKeyEvent((e) => { 327 // Bind onKeyEvent. When this Column component has focus, pressing F will toggle the focusable state of the second Text component. 328 if (e.keyCode === 2022 && e.type === KeyType.Down) { 329 this.textFocusable = !this.textFocusable; 330 } 331 // Bind onKeyEvent. When this Column component has focus, pressing G will toggle the enabled state of the third Text component. 332 if (e.keyCode === 2023 && e.type === KeyType.Down) { 333 this.textEnabled = !this.textEnabled; 334 } 335 }) 336 } 337} 338``` 339 340 341Operation result: 342 343 344 345 346The preceding example includes three steps: 347 348 349- As the first **Text** component does not have **focusable(true)** set, it is unfocusable. 350- The second **Text** component is set with **focusOnTouch(true)**, allowing it to gain focus on touch. Pressing the **Tab** key triggers focus traversal, but the focus remains on the second component. When the **F** key is pressed, the **onKeyEvent** callback toggles **focusable** to **false**, making the second **Text** component unfocusable, and the focus shifts to the next available focusable component, which is the third **Text** component. 351- Pressing the **G** key triggers the **onKeyEvent** callback, which sets **enabled** to **false**, making the third **Text** component unfocusable. The focus then automatically moves to the **Row** container, where the default configuration causes the focus to shift to **Button1**. 352 353## Default Focus 354 355### Default Focus on a Page 356 357```ts 358defaultFocus(value: boolean) 359``` 360 361Specifies whether to set the component as the default focus of the page. 362 363 364```ts 365// xxx.ets 366@Entry 367@Component 368struct morenjiaodian { 369 @State oneButtonColor: Color = Color.Gray; 370 @State twoButtonColor: Color = Color.Gray; 371 @State threeButtonColor: Color = Color.Gray; 372 373 build() { 374 Column({ space: 20 }) { 375 // You can use the up and down arrow keys on an external keyboard to move the focus between the three buttons. When a button gains focus, its color changes. When it loses focus, its color changes back. 376 Button('First Button') 377 .width(260) 378 .height(70) 379 .backgroundColor(this.oneButtonColor) 380 .fontColor(Color.Black) 381 // Listen for the focus obtaining event of the first component and change its color when it obtains focus. 382 .onFocus(() => { 383 this.oneButtonColor = Color.Green; 384 }) 385 // Listen for the focus loss event of the first component and change its color when it loses focus. 386 .onBlur(() => { 387 this.oneButtonColor = Color.Gray; 388 }) 389 390 Button('Second Button') 391 .width(260) 392 .height(70) 393 .backgroundColor(this.twoButtonColor) 394 .fontColor(Color.Black) 395 // Listen for the focus obtaining event of the second component and change its color when it obtains focus. 396 .onFocus(() => { 397 this.twoButtonColor = Color.Green; 398 }) 399 // Listen for the focus loss event of the second component and change its color when it loses focus. 400 .onBlur(() => { 401 this.twoButtonColor = Color.Grey; 402 }) 403 404 Button('Third Button') 405 .width(260) 406 .height(70) 407 .backgroundColor(this.threeButtonColor) 408 .fontColor(Color.Black) 409 // Set the default focus. 410 .defaultFocus(true) 411 // Listen for the focus obtaining event of the third component and change its color when it obtains focus. 412 .onFocus(() => { 413 this.threeButtonColor = Color.Green; 414 }) 415 // Listen for the focus loss event of the third component and change its color when it loses focus. 416 .onBlur(() => { 417 this.threeButtonColor = Color.Gray ; 418 }) 419 }.width('100%').margin({ top: 20 }) 420 } 421} 422``` 423 424 425 426The preceding example includes two steps: 427 428- The **defaultFocus(true)** is set on the third **Button** component, which means it gains focus by default when the page is loaded, displaying in green. 429- Pressing the **Tab** key triggers focus traversal, and since the third **Button** component is in focus, a focus frame appears around it. 430 431### Default Focus for Containers 432 433The default focus within a container is affected by [focus priority](#focus-group-and-focus-priority). 434 435**Differences Between defaultFocus and FocusPriority** 436 437[defaultFocus](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md#defaultfocus9) specifies the initial focus when the page loads. [FocusPriority](../reference/apis-arkui/arkui-ts/ts-universal-attributes-focus.md#focuspriority12) defines the order in which child components gain focus within a container. Behavior is undefined when both attributes are set in some scenarios. For example, a page's initial display cannot simultaneously meet the focus requirements of a component with **defaultFocus **and a high-priority component. 438 439Example 440 441```ts 442@Entry 443@Component 444struct Index { 445 build() { 446 Row() { 447 Button('Button1') 448 .defaultFocus(true) 449 Button('Button2') 450 .focusScopePriority('RowScope', FocusPriority.PREVIOUS) 451 }.focusScopeId('RowScope') 452 } 453} 454``` 455 456### Focus Chain for Pages/Containers 457 458**Overall Focus and Non-Overall Focus** 459 460- Overall focus: The entire page or container gains focus first, then the focus shifts to its child components. Examples include page transitions, route switches within **Navigation** components, focus group traversal, and when a container component proactively calls **requestFocusById**. 461 462- Non-overall focus: A specific component gains focus, pulling its parent components into focus. Examples include a **TextInput** component proactively obtaining focus or using the **Tab** key for traversal in non-focus group. 463 464**Formation of the Focus Chain in Overall Focus** 465 4661. Initial page focus: 467 468- The leaf node of the focus chain is the node with **defaultFocus** set. 469 470- If no **defaultFocus** is configured, the focus remains on the page's root container. 471 4722. Subsequent page focus: Focus is gained by the node that last held focus. 473 4743. Focus chain with priority configuration: 475 476- If a container has a component with a focus priority higher than **PREVIOUS**, the component with the highest priority gains focus. 477 478- If no component with a priority higher than **PREVIOUS** exists, the last focused node regains focus, such as when a window refocuses after being out of focus. 479 480 481## Focus Style 482 483 484```ts 485focusBox(style: FocusBoxStyle) 486``` 487 488Sets the system focus box style for the component. 489 490```ts 491import { ColorMetrics, LengthMetrics } from '@kit.ArkUI' 492 493@Entry 494@Component 495struct RequestFocusExample { 496 build() { 497 Column({ space: 30 }) { 498 Button("small black focus box") 499 .focusBox({ 500 margin: new LengthMetrics(0), 501 strokeColor: ColorMetrics.rgba(0, 0, 0), 502 }) 503 Button("large red focus box") 504 .focusBox({ 505 margin: LengthMetrics.px(20), 506 strokeColor: ColorMetrics.rgba(255, 0, 0), 507 strokeWidth: LengthMetrics.px(10) 508 }) 509 } 510 .alignItems(HorizontalAlign.Center) 511 .width('100%') 512 } 513} 514``` 515 516 517 518 519The preceding example includes two steps: 520 521- After the page opens, pressing the Tab key initiates focus traversal. The first **Button** gains focus, displaying a small, black focus box that is closely fitted to the edge. 522- Pressing the Tab key again shifts focus to the second **Button**, which features a large, red focus box with a thicker stroke and a more significant margin from the edge. 523 524## Active Focus Acquisition/Loss 525 526- Using **FocusController** APIs 527 528 You are advised to use **requestFocus** from **FocusController** for actively acquiring focus. It provides the following benefits: 529 - Takes effect in the current frame, preventing interference from subsequent component tree changes. 530 - Provides exception handling, aiding in troubleshooting focus acquisition issues. 531 - Prevents errors in multi-instance scenarios by avoiding incorrect instance retrieval. 532 533 You must first obtain an instance using the [getFocusController()](../reference/apis-arkui/js-apis-arkui-UIContext.md#getfocuscontroller12) API in **UIContext** and then use this instance to call the corresponding methods. 534 535 ```ts 536 requestFocus(key: string): void 537 ``` 538 Transfers focus to a component node by the component ID, which is effective immediately. 539 540 ```ts 541 clearFocus(): void 542 ``` 543 Clears the focus and forcibly moves the focus to the root container node of the page, causing other nodes in the focus chain to lose focus. 544 545- Using **focusControl** APIs 546 ```ts 547 requestFocus(value: string): boolean 548 ``` 549 550 Moves focus to a specified component, with the change taking effect in the next frame. 551 552 553```ts 554// focusTest.ets 555@Entry 556@Component 557struct RequestExample { 558 @State btColor: string = '#ff2787d9' 559 @State btColor2: string = '#ff2787d9' 560 561 build() { 562 Column({ space: 20 }) { 563 Column({ space: 5 }) { 564 Button('Button') 565 .width(200) 566 .height(70) 567 .fontColor(Color.White) 568 .focusOnTouch(true) 569 .backgroundColor(this.btColor) 570 .onFocus(() => { 571 this.btColor = '#ffd5d5d5' 572 }) 573 .onBlur(() => { 574 this.btColor = '#ff2787d9' 575 }) 576 .id("testButton") 577 578 Button('Button') 579 .width(200) 580 .height(70) 581 .fontColor(Color.White) 582 .focusOnTouch(true) 583 .backgroundColor(this.btColor2) 584 .onFocus(() => { 585 this.btColor2 = '#ffd5d5d5' 586 }) 587 .onBlur(() => { 588 this.btColor2 = '#ff2787d9' 589 }) 590 .id("testButton2") 591 592 Divider() 593 .vertical(false) 594 .width("80%") 595 .backgroundColor('#ff707070') 596 .height(10) 597 598 Button('FocusController.requestFocus') 599 .width(200).height(70).fontColor(Color.White) 600 .onClick(() => { 601 this.getUIContext().getFocusController().requestFocus("testButton") 602 }) 603 .backgroundColor('#ff2787d9') 604 605 Button("focusControl.requestFocus") 606 .width(200).height(70).fontColor(Color.White) 607 .onClick(() => { 608 focusControl.requestFocus("testButton2") 609 }) 610 .backgroundColor('#ff2787d9') 611 612 Button("clearFocus") 613 .width(200).height(70).fontColor(Color.White) 614 .onClick(() => { 615 this.getUIContext().getFocusController().clearFocus() 616 }) 617 .backgroundColor('#ff2787d9') 618 } 619 } 620 .width('100%') 621 .height('100%') 622 } 623} 624``` 625 626 627 628The preceding example includes three steps: 629 630- When the **FocusController.requestFocus** button is clicked, the first button gains focus. 631- When the **focusControl.requestFocus** button is clicked, the second button gains focus. 632- When the **clearFocus** button is clicked, the second button loses focus. 633 634## Focus Group and Focus Priority 635 636```ts 637focusScopePriority(scopeId: string, priority?: FocusPriority) 638``` 639 640Sets the focus priority of this component in a specified container. It must be used together with **focusScopeId**. 641 642 643```ts 644focusScopeId(id: string, isGroup?: boolean) 645``` 646 647Assigns an ID to this container component and specifies whether the container is a focus group. Focus groups should not be mixed with **tabIndex** usage. 648 649```ts 650// focusTest.ets 651@Entry 652@Component 653struct FocusableExample { 654 @State inputValue: string = '' 655 656 build() { 657 Scroll() { 658 Row({ space: 20 }) { 659 Column({ space: 20 }) { // Labeled as Column1. 660 Column({ space: 5 }) { 661 Button('Group1') 662 .width(165) 663 .height(40) 664 .fontColor(Color.White) 665 Row({ space: 5 }) { 666 Button() 667 .width(80) 668 .height(40) 669 .fontColor(Color.White) 670 Button() 671 .width(80) 672 .height(40) 673 .fontColor(Color.White) 674 } 675 Row({ space: 5 }) { 676 Button() 677 .width(80) 678 .height(40) 679 .fontColor(Color.White) 680 Button() 681 .width(80) 682 .height(40) 683 .fontColor(Color.White) 684 } 685 }.borderWidth(2).borderColor(Color.Red).borderStyle(BorderStyle.Dashed) 686 Column({ space: 5 }) { 687 Button('Group2') 688 .width(165) 689 .height(40) 690 .fontColor(Color.White) 691 Row({ space: 5 }) { 692 Button() 693 .width(80) 694 .height(40) 695 .fontColor(Color.White) 696 Button() 697 .width(80) 698 .height(40) 699 .fontColor(Color.White) 700 .focusScopePriority('ColumnScope1', FocusPriority.PRIOR) // Focuses when Column1 first gains focus. 701 } 702 Row({ space: 5 }) { 703 Button() 704 .width(80) 705 .height(40) 706 .fontColor(Color.White) 707 Button() 708 .width(80) 709 .height(40) 710 .fontColor(Color.White) 711 } 712 }.borderWidth(2).borderColor(Color.Green).borderStyle(BorderStyle.Dashed) 713 } 714 .focusScopeId('ColumnScope1') 715 Column({ space: 5 }) { // Labeled as Column2. 716 TextInput({placeholder: 'input', text: this.inputValue}) 717 .onChange((value: string) => { 718 this.inputValue = value 719 }) 720 .width(156) 721 Button('Group3') 722 .width(165) 723 .height(40) 724 .fontColor(Color.White) 725 Row({ space: 5 }) { 726 Button() 727 .width(80) 728 .height(40) 729 .fontColor(Color.White) 730 Button() 731 .width(80) 732 .height(40) 733 .fontColor(Color.White) 734 } 735 Button() 736 .width(165) 737 .height(40) 738 .fontColor(Color.White) 739 .focusScopePriority('ColumnScope2', FocusPriority.PREVIOUS) // Focuses when Column2 first gains focus. 740 Row({ space: 5 }) { 741 Button() 742 .width(80) 743 .height(40) 744 .fontColor(Color.White) 745 Button() 746 .width(80) 747 .height(40) 748 .fontColor(Color.White) 749 } 750 Button() 751 .width(165) 752 .height(40) 753 .fontColor(Color.White) 754 Row({ space: 5 }) { 755 Button() 756 .width(80) 757 .height(40) 758 .fontColor(Color.White) 759 Button() 760 .width(80) 761 .height(40) 762 .fontColor(Color.White) 763 } 764 }.borderWidth(2).borderColor(Color.Orange).borderStyle(BorderStyle.Dashed) 765 .focusScopeId('ColumnScope2', true) // Column2 is a focus group. 766 }.alignItems(VerticalAlign.Top) 767 } 768 } 769} 770``` 771 772 773 774 775 776 777The preceding example includes two steps: 778 779- The input box is set with a focus group, which means that when the **Tab** key is pressed, the focus quickly moves out from the input, and when arrow keys are used, the focus stays within the input. 780- The **Column** component in the upper left corner does not have a focus group set. Therefore, focus can only be traversed one by one with the **Tab** key. 781 782## Focus and Key Events 783 784When a component is in focus and has either an **onClick** or **TapGesture** event defined, pressing the **Enter** key or spacebar triggers the associated event callback. 785 786> **NOTE** 787> 788> 1. If the **onClick** or **TapGesture** event is triggered by pressing the **Enter** key or spacebar, the event does not bubble up by default. This means that the parent component's corresponding [key event](../reference/apis-arkui/arkui-ts/ts-universal-events-key.md) is not triggered synchronously. 789> 2. The key event (**onKeyEvent**) bubbles up by default, which means that it will also trigger the parent component's key event callback. 790> 3. If the component has both an **onClick** event and an **onKeyEvent**, pressing the **Enter** key or spacebar trigger both events. 791> 4. The component's response to the **onClick** event is independent of whether the focus is activated or not. 792 793``` 794@Entry 795@Component 796struct FocusOnclickExample { 797 @State count: number = 0 798 @State name: string = 'Button' 799 800 build() { 801 Column() { 802 Button(this.name) 803 .fontSize(30) 804 .onClick(() => { 805 this.count++ 806 if (this.count <= 0) { 807 this.name = "count is negative number" 808 } else if (this.count % 2 === 0) { 809 this.name = "count is even number" 810 } else { 811 this.name = "count is odd number" 812 } 813 }).height(60) 814 }.height('100%').width('100%').justifyContent(FlexAlign.Center) 815 } 816} 817``` 818 819 820## Component Focusability 821 822 823 **Table 1** Focusability of basic components 824 825| Basic Component | Focusable| Default Value of focusable| 826| ---------------------------------------- | ------- | ------------ | 827| [AlphabetIndexer](../reference/apis-arkui/arkui-ts/ts-container-alphabet-indexer.md) | Yes | true | 828| [Blank](../reference/apis-arkui/arkui-ts/ts-basic-components-blank.md) | No | false | 829| [Button](../reference/apis-arkui/arkui-ts/ts-basic-components-button.md) | Yes | true | 830| [CalendarPicker](../reference/apis-arkui/arkui-ts/ts-basic-components-calendarpicker.md) | Yes | true | 831| [Checkbox](../reference/apis-arkui/arkui-ts/ts-basic-components-checkbox.md) | Yes | true | 832| [CheckboxGroup](../reference/apis-arkui/arkui-ts/ts-basic-components-checkboxgroup.md) | Yes | true | 833| [ContainerSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-containerspan.md) | No | false | 834| [DataPanel](../reference/apis-arkui/arkui-ts/ts-basic-components-datapanel.md) | Yes | false | 835| [DatePicker](../reference/apis-arkui/arkui-ts/ts-basic-components-datepicker.md) | Yes | true | 836| [Divider](../reference/apis-arkui/arkui-ts/ts-basic-components-divider.md) | Yes | false | 837| [Gauge](../reference/apis-arkui/arkui-ts/ts-basic-components-gauge.md) | Yes | false | 838| [Image](../reference/apis-arkui/arkui-ts/ts-basic-components-image.md) | Yes | false | 839| [ImageAnimator](../reference/apis-arkui/arkui-ts/ts-basic-components-imageanimator.md) | No | false | 840| [ImageSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-imagespan.md) | No | false | 841| [LoadingProgress](../reference/apis-arkui/arkui-ts/ts-basic-components-loadingprogress.md) | Yes | true | 842| [Marquee](../reference/apis-arkui/arkui-ts/ts-basic-components-marquee.md) | No | false | 843| [Menu](../reference/apis-arkui/arkui-ts/ts-basic-components-menu.md) | Yes | true | 844| [MenuItem](../reference/apis-arkui/arkui-ts/ts-basic-components-menuitem.md) | Yes | true | 845| [MenuItemGroup](../reference/apis-arkui/arkui-ts/ts-basic-components-menuitemgroup.md) | No | false | 846| [Navigation](../reference/apis-arkui/arkui-ts/ts-basic-components-navigation.md) | Yes | true | 847| [NavRouter](../reference/apis-arkui/arkui-ts/ts-basic-components-navrouter.md) | No | false | 848| [NavDestination](../reference/apis-arkui/arkui-ts/ts-basic-components-navdestination.md) | Yes | true | 849| [PatternLock](../reference/apis-arkui/arkui-ts/ts-basic-components-patternlock.md) | Yes | true | 850| [Progress](../reference/apis-arkui/arkui-ts/ts-basic-components-progress.md) | Yes | true | 851| [QRCode](../reference/apis-arkui/arkui-ts/ts-basic-components-qrcode.md) | Yes | true | 852| [Radio](../reference/apis-arkui/arkui-ts/ts-basic-components-radio.md) | Yes | true | 853| [Rating](../reference/apis-arkui/arkui-ts/ts-basic-components-rating.md) | Yes | true | 854| [RichEditor](../reference/apis-arkui/arkui-ts/ts-basic-components-richeditor.md) | Yes | true | 855| [RichText](../reference/apis-arkui/arkui-ts/ts-basic-components-richtext.md) | No | false | 856| [ScrollBar](../reference/apis-arkui/arkui-ts/ts-basic-components-scrollbar.md) | No | false | 857| [Search](../reference/apis-arkui/arkui-ts/ts-basic-components-search.md) | Yes | true | 858| [Select](../reference/apis-arkui/arkui-ts/ts-basic-components-select.md) | Yes | true | 859| [Slider](../reference/apis-arkui/arkui-ts/ts-basic-components-slider.md) | Yes | true | 860| [Span](../reference/apis-arkui/arkui-ts/ts-basic-components-span.md) | No | false | 861| [Stepper](../reference/apis-arkui/arkui-ts/ts-basic-components-stepper.md) | Yes | true | 862| [StepperItem](../reference/apis-arkui/arkui-ts/ts-basic-components-stepperitem.md) | Yes | true | 863| [SymbolSpan](../reference/apis-arkui/arkui-ts/ts-basic-components-symbolSpan.md) | No | false | 864| [SymbolGlyph](../reference/apis-arkui/arkui-ts/ts-basic-components-symbolGlyph.md) | No | false | 865| [Text](../reference/apis-arkui/arkui-ts/ts-basic-components-text.md) | Yes | false | 866| [TextArea](../reference/apis-arkui/arkui-ts/ts-basic-components-textarea.md) | No | false | 867| [TextClock](../reference/apis-arkui/arkui-ts/ts-basic-components-textclock.md) | No | false | 868| [TextInput](../reference/apis-arkui/arkui-ts/ts-basic-components-textinput.md) | Yes | true | 869| [TextPicker](../reference/apis-arkui/arkui-ts/ts-basic-components-textpicker.md) | Yes | true | 870| [TextTimer](../reference/apis-arkui/arkui-ts/ts-basic-components-texttimer.md) | No | false | 871| [TimePicker](../reference/apis-arkui/arkui-ts/ts-basic-components-timepicker.md) | No | false | 872| [Toggle](../reference/apis-arkui/arkui-ts/ts-basic-components-toggle.md) | Yes | true | 873| [XComponent](../reference/apis-arkui/arkui-ts/ts-basic-components-xcomponent.md) | Yes | false | 874 875 **Table 2** Focusability of container components 876 877| Container Component | Focusable| Default Value of focusable| 878| ---------------------------------------- | ----- | ------------ | 879| [Badge](../reference/apis-arkui/arkui-ts/ts-container-badge.md) | No | false | 880| [Column](../reference/apis-arkui/arkui-ts/ts-container-column.md) | Yes | true | 881| [ColumnSplit](../reference/apis-arkui/arkui-ts/ts-container-columnsplit.md) | Yes | true | 882| [Counter](../reference/apis-arkui/arkui-ts/ts-container-counter.md) | Yes | false | 883| [EmbeddedComponent](../reference/apis-arkui/arkui-ts/ts-container-embedded-component.md) | No | false | 884| [Flex](../reference/apis-arkui/arkui-ts/ts-container-flex.md) | Yes | true | 885| [FlowItem](../reference/apis-arkui/arkui-ts/ts-container-flowitem.md) | Yes | true | 886| [FolderStack](../reference/apis-arkui/arkui-ts/ts-container-folderstack.md) | Yes | true | 887| [FormLink](../reference/apis-arkui/arkui-ts/ts-container-formlink.md) | No | false | 888| [GridCol](../reference/apis-arkui/arkui-ts/ts-container-gridcol.md) | Yes | true | 889| [GridRow](../reference/apis-arkui/arkui-ts/ts-container-gridrow.md) | Yes | true | 890| [Grid](../reference/apis-arkui/arkui-ts/ts-container-grid.md) | Yes | true | 891| [GridItem](../reference/apis-arkui/arkui-ts/ts-container-griditem.md) | Yes | true | 892| [Hyperlink](../reference/apis-arkui/arkui-ts/ts-container-hyperlink.md) | Yes | true | 893| [List](../reference/apis-arkui/arkui-ts/ts-container-list.md) | Yes | true | 894| [ListItem](../reference/apis-arkui/arkui-ts/ts-container-listitem.md) | Yes | true | 895| [ListItemGroup](../reference/apis-arkui/arkui-ts/ts-container-listitemgroup.md) | Yes | true | 896| [Navigator](../reference/apis-arkui/arkui-ts/ts-container-navigator.md) | Yes | true | 897| [Refresh](../reference/apis-arkui/arkui-ts/ts-container-refresh.md) | Yes | true | 898| [RelativeContainer](../reference/apis-arkui/arkui-ts/ts-container-relativecontainer.md) | No | false | 899| [Row](../reference/apis-arkui/arkui-ts/ts-container-row.md) | Yes | true | 900| [RowSplit](../reference/apis-arkui/arkui-ts/ts-container-rowsplit.md) | Yes | true | 901| [Scroll](../reference/apis-arkui/arkui-ts/ts-container-scroll.md) | Yes | true | 902| [SideBarContainer](../reference/apis-arkui/arkui-ts/ts-container-sidebarcontainer.md) | Yes | true | 903| [Stack](../reference/apis-arkui/arkui-ts/ts-container-stack.md) | Yes | true | 904| [Swiper](../reference/apis-arkui/arkui-ts/ts-container-swiper.md) | Yes | true | 905| [Tabs](../reference/apis-arkui/arkui-ts/ts-container-tabs.md) | Yes | true | 906| [TabContent](../reference/apis-arkui/arkui-ts/ts-container-tabcontent.md) | Yes | true | 907| [WaterFlow](../reference/apis-arkui/arkui-ts/ts-container-waterflow.md) | No | false | 908| [WithTheme](../reference/apis-arkui/arkui-ts/ts-container-with-theme.md) | Yes | true | 909 910 **Table 3** Focusability of media components 911 912| Media Component | Focusable| Default Value of focusable| 913| ---------------------------------------- | ----- | ------------ | 914| [Video](../reference/apis-arkui/arkui-ts/ts-media-components-video.md) | Yes | true | 915