1# Focus Control 2 3Focus control attributes set whether a component is focusable and how it participates in focus navigation. 4 5> **NOTE** 6> 7> - The initial APIs of this module are supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version. 8> 9> - Custom components are inherently unfocusable, and setting [focusable](#focusable) and [enabled](ts-universal-attributes-enable.md#enabled) attributes to **false** or setting the [visibility](ts-universal-attributes-visibility.md#visibility) attribute to **Hidden** or **None** does not impact their child components' capability to gain focus. 10> 11> - Components can actively acquire focus independently of the window's focus state. 12> 13> - For details about focus development, see [Focus Event](../../../ui/arkts-common-events-focus-event.md). 14 15## focusable 16 17focusable(value: boolean): T 18 19Sets whether the component is focusable. 20 21**Atomic service API**: This API can be used in atomic services since API version 11. 22 23**System capability**: SystemCapability.ArkUI.ArkUI.Full 24 25**Parameters** 26 27| Name| Type | Mandatory| Description | 28| ------ | ------- | ---- | ------------------------------------------------------------ | 29| value | boolean | Yes | Whether the component is focusable.<br>**true**: The component is focusable.<br>**false**: The component is not focusable.<br>**NOTE**<br>Components that have default interaction logic, such as [Button](ts-basic-components-button.md) and [TextInput](ts-basic-components-textinput.md), are focusable by default. Other components, such as [Text](ts-basic-components-text.md) and [Image](ts-basic-components-image.md), are not focusable by default. Only focusable components can trigger a [focus event](ts-universal-focus-event.md).| 30 31**Return value** 32 33| Type| Description| 34| -------- | -------- | 35| T | Current component.| 36 37## tabIndex<sup>9+</sup> 38 39tabIndex(index: number): T 40 41Sets the Tab order of the component in sequential focus navigation with the **Tab** key. 42 43**Atomic service API**: This API can be used in atomic services since API version 11. 44 45**System capability**: SystemCapability.ArkUI.ArkUI.Full 46 47**Parameters** 48 49| Name| Type | Mandatory| Description | 50| ------ | ------ | ---- | ------------------------------------------------------------ | 51| index | number | Yes | Tab order of the component in sequential focus navigation with the **Tab** key. When components with positive **tabIndex** values are present, only these components are reachable through sequential focus navigation, and they are navigated cyclically in ascending order based on the **tabIndex** value. When components with positive **tabIndex** values are not present, those components with a **tabIndex** value of **0** are navigated based on the preset focus navigation rule.<br>The [UiExtension](../js-apis-arkui-uiExtension.md) component does not support **tabIndex**. As such, using **tabIndex** on [hierarchical pages](../../../ui/arkts-common-events-focus-event.md#basic-concepts) that contain **UiExtension** components may lead to disordered focus navigation.<br>- **tabIndex** >= 0: The component is focusable and can be reached through sequential keyboard navigation.<br>- **tabIndex** < 0 (usually **tabIndex** = -1): The component is focusable, but cannot be reached through sequential keyboard navigation.<br>Default value: **0**<br> **NOTE**<br> **tabIndex** and **focusScopeId** cannot be used together. 52| 53 54**Return value** 55 56| Type| Description| 57| -------- | -------- | 58| T | Current component.| 59 60## defaultFocus<sup>9+</sup> 61 62defaultFocus(value: boolean): T 63 64Specifies whether to set this component as the default focus of the current [hierarchical page](../../../ui/arkts-common-events-focus-event.md#basic-concepts). 65 66> **NOTE** 67> 68> This setting applies to pages that support routing or modal-type container components, such as **Page**, **NaviDestination**, **NavBar**, **PopUp**, and **Dialog**. 69 70**Atomic service API**: This API can be used in atomic services since API version 11. 71 72**System capability**: SystemCapability.ArkUI.ArkUI.Full 73 74**Parameters** 75 76| Name| Type | Mandatory| Description | 77| ------ | ------- | ---- | ------------------------------------------------------------ | 78| value | boolean | Yes | Whether to set the component as the default focus of the current [hierarchical page](../../../ui/arkts-common-events-focus-event.md#basic-concepts). This parameter takes effect only when the hierarchical page is new and accessed for the first time.<br>Default value: **false**<br>**NOTE**<br>The value **true** means to set the component as the default focus, and the value **false** has no effect.<br>If no component on the hierarchical page has **defaultFocus(true)** set:<br>For API version 11 and earlier, the default focus is on the first focusable non-container component.<br>For API version versions later than 11, the default focus is on the hierarchical page's root container.<br>If **defaultFocus(true)** is set for multiple components on the hierarchical page, the first component found in the component tree depth-first traversal is used as the default focus.| 79 80**Return value** 81 82| Type| Description| 83| -------- | -------- | 84| T | Current component.| 85 86## groupDefaultFocus<sup>9+</sup> 87 88groupDefaultFocus(value: boolean): T 89 90Specifies whether to set the component as the default focus of the container. 91 92**Atomic service API**: This API can be used in atomic services since API version 11. 93 94**System capability**: SystemCapability.ArkUI.ArkUI.Full 95 96**Parameters** 97 98| Name| Type | Mandatory| Description | 99| ------ | ------- | ---- | ------------------------------------------------------------ | 100| value | boolean | Yes | Whether to set the component as the default focus of the parent container. This parameter takes effect only when the container is new and obtains focus for the first time. <br>**true**: The component is the default focus of the parent container.<br>**false**: The component is not the default focus of the parent container.<br>Default value: **false**<br>**NOTE**<br>This parameter must be used together with [tabIndex](#tabindex9). When **tabIndex** is set for a container and **groupDefaultFocus(true)** is set for a child in the container or for the container itself, then when the container obtains focus for the first time through sequential Tab navigation, the focus automatically moves to the specified component. If **groupDefaultFocus(true)** is set for multiple components in the container (including the container itself), the first component found in the component tree in-depth traversal receives the focus.| 101 102**Return value** 103 104| Type| Description| 105| -------- | -------- | 106| T | Current component.| 107 108## focusOnTouch<sup>9+</sup> 109 110focusOnTouch(value: boolean): T 111 112Sets whether the component is focusable on touch. 113 114**Atomic service API**: This API can be used in atomic services since API version 11. 115 116**System capability**: SystemCapability.ArkUI.ArkUI.Full 117 118**Parameters** 119 120| Name| Type | Mandatory| Description | 121| ------ | ------- | ---- | ------------------------------------------------------------ | 122| value | boolean | Yes | Whether the component is focusable on touch. <br>**true**: The component is focusable on touch.<br>**false**: The component is not focusable on touch.<br>Default value: **false**<br>**NOTE**<br>The component is focusable only when it is touchable.| 123 124**Return value** 125 126| Type| Description| 127| -------- | -------- | 128| T | Current component.| 129 130## focusBox<sup>12+</sup> 131 132focusBox(style: FocusBoxStyle): T 133 134Sets the system focus box style for the component. 135 136**Atomic service API**: This API can be used in atomic services since API version 12. 137 138**System capability**: SystemCapability.ArkUI.ArkUI.Full 139 140**Parameters** 141 142| Name| Type| Mandatory| Description| 143| ---- | ---- | ---- | ---- | 144| style | [FocusBoxStyle](#focusboxstyle12) | Yes | System focus box style for the component.<br>**NOTE**<br>This style affects only the components that display the system focus box during focus traversal.| 145 146**Return value** 147 148| Type| Description| 149| -------- | -------- | 150| T | Current component.| 151 152## focusControl<sup>9+</sup> 153 154Implements focus control. 155 156**Atomic service API**: This API can be used in atomic services since API version 11. 157 158### requestFocus<sup>9+</sup> 159 160requestFocus(value: string): boolean 161 162Requests focus transfer to the specified component during the next frame rendering. This global API provides asynchronous focus control. 163For scenarios requiring immediate focus changes, it is recommended that you use the focus synchronization transfer API [requestFocus](../js-apis-arkui-UIContext.md#requestfocus12) in **FocusController**. 164 165**Atomic service API**: This API can be used in atomic services since API version 11. 166 167**Parameters** 168 169| Name| Type| Mandatory| Description| 170| ----- | ------ | ---- | ---- | 171| value | string | Yes | String bound to the target component using **key(value: string)** or **id(value: string)**.| 172 173**Return value** 174 175| Type| Description| 176| ------- | ---- | 177| boolean | Returns whether focus transfer is successfully requested for the target component. Returns **true** if the target component exists and can receive focus; returns **false** otherwise.| 178 179> **NOTE** 180> 181> The following components support focus control: [TextInput](ts-basic-components-textinput.md), [TextArea](ts-basic-components-textarea.md), [Search](ts-basic-components-search.md), [Button](ts-basic-components-button.md), [Text](ts-basic-components-text.md), [Image](ts-basic-components-image.md), [List](ts-container-list.md), [Grid](ts-container-grid.md). Currently, the running effect of the focus event can be displayed only on a real device. 182 183## FocusBoxStyle<sup>12+</sup> 184 185**Atomic service API**: This API can be used in atomic services since API version 12. 186 187| Name| Type| Mandatory| Description| 188| ---- | ---- | ---- | ---- | 189| margin | [LengthMetrics](../js-apis-arkui-graphics.md#lengthmetrics12) | No| Distance of the focus box from the component's edge.<br>A positive number indicates the outside, and a negative number indicates the inside. The value cannot be in percentage.| 190| strokeColor | [ColorMetrics](../js-apis-arkui-graphics.md#colormetrics12) | No| Stroke color of the focus box.| 191| strokeWidth | [LengthMetrics](../js-apis-arkui-graphics.md#lengthmetrics12) | No| Stroke width of the focus box.<br>Negative numbers and percentages are not supported.| 192 193## focusScopePriority<sup>12+</sup> 194 195focusScopePriority(scopeId: string, priority?: FocusPriority): T 196 197Sets the focus priority of this component in a specified container. It must be used together with **focusScopeId**. 198 199**Atomic service API**: This API can be used in atomic services since API version 12. 200 201**System capability**: SystemCapability.ArkUI.ArkUI.Full 202 203**Parameters** 204 205| Name| Type | Mandatory| Description | 206| ------ | ------- | ---- | ------------------------------------------------------------ | 207| scopeId | string | Yes | ID of the container component where the current component's focus priority takes effect.<br>**NOTE**<br>1. The current component must be inside the container identified by **scopeId** or inside a sub-container of that container.<br>2. A component cannot set multiple priorities.<br>3. A container component with **focusScopeId** set cannot have its priority set.| 208| priority | [FocusPriority](#focuspriority12) | No | Focus priority.<br>**NOTE**<br>If **priority** is not set, **AUTO** is used by default.<br>Impact of the priority on focus traversal and component focus:<br>1. When the container gains focus as a whole (hierarchical page level switching/focus switching to a focus group/container component requesting focus with **requestFocus**), if there is a component with a priority of **PREVIOUS** within the container, that component gains focus; otherwise, the last focused component does.<br>2. When a container does not gain focus as a whole (using **Tab** or arrow keys in non-focus group scenarios), the highest priority component gets focus on first focus; subsequent focus follows position order regardless of priority.| 209 210**Return value** 211 212| Type| Description| 213| -------- | -------- | 214| T | Current component.| 215 216### FocusPriority<sup>12+</sup> 217 218**Atomic service API**: This API can be used in atomic services since API version 12. 219 220**System capability**: SystemCapability.ArkUI.ArkUI.Full 221 222| Name | Description | 223| ----------- | --------- | 224| AUTO | Default priority, that is, the focus priority assigned by default.| 225| PRIOR | Priority that indicates the component is prioritized in the container. This level is higher than **AUTO**.| 226| PREVIOUS | Priority of a previously focused node in the container. This level is higher than **PRIOR**.| 227 228### KeyProcessingMode<sup>15+</sup> 229 230Enumerates the modes for processing key events. 231 232**Atomic service API**: This API can be used in atomic services since API version 15. 233 234**System capability**: SystemCapability.ArkUI.ArkUI.Full 235 236| Name | Value | Description | 237| -----------| ----------- | --------- | 238| FOCUS_NAVIGATION | 0 | Default value. When the current component does not consume the key event, focus navigation using the **Tab** and arrow keys preferentially stays within the current container.| 239| ANCESTOR_EVENT | 1 | When the current component does not consume the key event, focus navigation using the **Tab** and arrow keys is bubbled up to the parent component.| 240 241## focusScopeId<sup>12+</sup> 242 243focusScopeId(id: string, isGroup?: boolean): T 244 245Assigns an ID to this container component and specifies whether the container is a focus group. 246 247**Atomic service API**: This API can be used in atomic services since API version 12. 248 249**System capability**: SystemCapability.ArkUI.ArkUI.Full 250 251**Parameters** 252 253| Name| Type | Mandatory| Description | 254| ------ | ------- | ---- | ------------------------------------------------------------ | 255| id | string | Yes | ID of the current container component.<br>**NOTE**<br>The ID must be unique within a single [hierarchical page](../../../ui/arkts-common-events-focus-event.md#basic-concepts).| 256| isGroup | boolean | No | Whether the current container component is a focus group. <br>**true**: The current container component is a focus group.<br>**false**: The current container component is not a focus group.<br> Default value: **false**.<br>**NOTE**<br>Focus groups cannot be nested and should not be configured repeatedly.<br> The focus group and **tabIndex** cannot be used together.<br>The focus group enables the container and its elements to navigate focus according to the focus group rules as follows:<br>1. Only arrow keys are allowed for focus traversal within the focus group; the **Tab** key will move the focus out of the focus group.<br>2. When arrow keys are used to move the focus from outside the focus group to inside, if there is a component with a priority of **PREVIOUS** within the focus group, that component gains focus; otherwise, the last focused component does.| 257 258**Return value** 259 260| Type| Description| 261| -------- | -------- | 262| T | Current component.| 263 264## focusScopeId<sup>14+</sup> 265 266focusScopeId(id: string, isGroup?: boolean, arrowStepOut?: boolean): T 267 268Assigns an ID to this container component and specifies whether the container is a focus group. 269 270**System capability**: SystemCapability.ArkUI.ArkUI.Full 271 272**Parameters** 273 274| Name| Type | Mandatory| Description | 275| ------ | ------- | ---- | ------------------------------------------------------------ | 276| id | string | Yes | ID of the current container component.<br>**NOTE**<br>The ID must be unique within a single [hierarchical page](../../../ui/arkts-common-events-focus-event.md#basic-concepts).<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 277| isGroup | boolean | No | Whether the current container component is a focus group. <br>**true**: The current container component is a focus group.<br>**false**: The current container component is not a focus group.<br> Default value: **false**.<br>**NOTE**<br>Focus groups cannot be nested and should not be configured repeatedly.<br> The focus group and **tabIndex** cannot be used together.<br>The focus group enables the container and its elements to navigate focus according to the focus group rules as follows:<br>1. Only arrow keys are allowed for focus traversal within the focus group; the **Tab** key will move the focus out of the focus group.<br>2. When arrow keys are used to move the focus from outside the focus group to inside, if there is a component with a priority of **PREVIOUS** within the focus group, that component gains focus; otherwise, the last focused component does.<br>**Atomic service API**: This API can be used in atomic services since API version 12.| 278| arrowStepOut<sup>14+</sup> | boolean | No | Whether the focus can be moved out of the current focus group using arrow keys. <br>**true**: The focus can be moved out of the current focus group using arrow keys.<br>**false**: The focus cannot be moved out of the current focus group using arrow keys.<br> The default value is **true**.<br>**Atomic service API**: This API can be used in atomic services since API version 14.| 279 280**Return value** 281 282| Type| Description| 283| -------- | -------- | 284| T | Current component.| 285 286## tabStop<sup>14+</sup> 287 288tabStop(isTabStop: boolean): T 289 290Sets whether this container component is a focus stop. During focus traversal, the focus stops at the container component serving as a focus stop. 291 292**Atomic service API**: This API can be used in atomic services since API version 14. 293 294**System capability**: SystemCapability.ArkUI.ArkUI.Full 295 296**Parameters** 297 298| Name| Type | Mandatory| Description | 299| ------ | ------- | ---- | ------------------------------------------------------------ | 300| isTabStop | boolean | Yes | Whether the current container component is a focus stop. <br>**true**: The current container component is a focus stop.<br>**false**: The current container component is not a focus stop.<br>**NOTE**<br>1. To configure **tabStop**, make sure the component is a container and has focusable child components. By default, container components cannot directly gain focus.<br> 2. When [requestFocus](../js-apis-arkui-UIContext.md#requestfocus12) is used for requesting focus, if the component is a container and **tabStop** is configured, the focus can stop at the container. If **tabStop** is not configured, the component can still gain focus, even if there are other components in the focus chain with **tabStop** configured.<br>3. Containers with **tabStop** configured should not be nested more than two levels deep.<br>Focus traversal rules with **tabStop**:<br>1. During focus traversal using the **Tab** key or arrow keys, the focus stops at components with **tabStop** configured. If the focus is inside a container with **tabStop** configured, it can move to the next focusable component within the container. If the focus is outside such a container, it can move to the next focusable component outside the container.<br>2. When the focus is on a container with **tabStop** configured: Pressing **Enter** moves the focus to the first focusable component inside the container.<br>Pressing **ESC** moves the focus back to the last component with **tabStop** configured within the current [hierarchical page](../../../ui/arkts-common-events-focus-event.md#basic-concepts).<br>Pressing the spacebar triggers the **onClick** event of the container.<br>3. Whenever possible, avoid configuring **tabStop** on the root container. If **tabStop** is configured on the root container, the following behaviors will occur:<br>- Using [clearFocus](../js-apis-arkui-UIContext.md#clearfocus12) to clear the focus to the root container and then pressing **Enter** will move the focus to the previously focused component inside the root container.<br>- Using **ESC** to clear the focus to the root container and then pressing **Enter** will move the focus to the first focusable component inside the root container.| 301 302**Return value** 303 304| Type| Description| 305| -------- | -------- | 306| T | Current component.| 307 308**Example for describing the keys and focusable components during focus traversal** 309 310 311 312If the current focus is on **button2**, pressing the **Tab** key will move the focus to **Column3**. Pressing the **Tab** key again will move the focus back to **button1**. 313 314## nextFocus<sup>18+</sup> 315 316nextFocus(nextStep: Optional\<FocusMovement>): T 317 318Sets the custom focus movement logic for the component. 319 320**Atomic service API**: This API can be used in atomic services since API version 18. 321 322**System capability**: SystemCapability.ArkUI.ArkUI.Full 323 324**Parameters** 325 326| Name| Type | Mandatory| Description | 327| ------ | ------- | ---- | ------------------------------------------------------------ | 328| nextStep | [FocusMovement](#focusmovement18) | No| Custom focus movement logic of the component.<br>**NOTE**<br>The default value resets **nextStep** to empty.<br>If custom focus movement is not set or the specified component does not exist, the default focus movement logic applies.| 329 330**Return value** 331 332| Type| Description| 333| -------- | -------- | 334| T | Current component.| 335 336## FocusMovement<sup>18+</sup> 337 338Sets the target component for focus movement based on key presses. If it is not specified, the default focus movement logic applies. 339 340**Atomic service API**: This API can be used in atomic services since API version 18. 341 342**System capability**: SystemCapability.ArkUI.ArkUI.Full 343 344| Name| Type| Read-Only/Optional| Description| 345| ---- | ---- | ---- | ---- | 346| forward | string | Optional| ID of the component to focus on when the **Tab** key is pressed.<br>The default value resets **forward** to empty.| 347| backward | string | Optional| ID of the component to focus on when **Shift+Tab** is pressed.<br>The default value resets **backward** to empty.| 348| up | string | Optional| ID of the component to focus on when the up arrow key is pressed.<br>The default value resets **up** to empty.| 349| down | string | Optional| ID of the component to focus on when the down arrow key is pressed.<br>The default value resets **down** to empty.| 350| left | string | Optional| ID of the component to focus on when the left arrow key is pressed.<br>The default value resets **left** to empty.| 351| right | string | Optional| ID of the component to focus on when the right arrow key is pressed.<br>The default value resets **right** to empty.| 352 353## Example 354 355### Example 1: Setting Focus and Focus Traversal Effects for Components 356 357This example shows how to use **defaultFocus**, **groupDefaultFocus**, and **focusOnTouch**. **defaultFocus** sets the bound component as the initial focus after the [hierarchical page](../../../ui/arkts-common-events-focus-event.md#basic-concepts) is created. **groupDefaultFocus** sets the bound component as the initial focus after the container with the specified **tabIndex** is created. **focusOnTouch** sets the bound component to obtain focus upon being clicked. 358 359```ts 360// focusTest.ets 361@Entry 362@Component 363struct FocusableExample { 364 @State inputValue: string = ''; 365 366 build() { 367 Scroll() { 368 Row({ space: 20 }) { 369 Column({ space: 20 }) { 370 Column({ space: 5 }) { 371 Button('Group1') 372 .width(165) 373 .height(40) 374 .fontColor(Color.White) 375 .focusOnTouch(true) // The button is focusable on touch. 376 Row({ space: 5 }) { 377 Button() 378 .width(80) 379 .height(40) 380 .fontColor(Color.White) 381 Button() 382 .width(80) 383 .height(40) 384 .fontColor(Color.White) 385 .focusOnTouch(true) // The button is focusable on touch. 386 } 387 Row({ space: 5 }) { 388 Button() 389 .width(80) 390 .height(40) 391 .fontColor(Color.White) 392 Button() 393 .width(80) 394 .height(40) 395 .fontColor(Color.White) 396 } 397 }.borderWidth(2).borderColor(Color.Red).borderStyle(BorderStyle.Dashed) 398 .tabIndex(1) // The column is the initial component to have focus in sequential keyboard navigation. 399 Column({ space: 5 }) { 400 Button('Group2') 401 .width(165) 402 .height(40) 403 .fontColor(Color.White) 404 Row({ space: 5 }) { 405 Button() 406 .width(80) 407 .height(40) 408 .fontColor(Color.White) 409 Button() 410 .width(80) 411 .height(40) 412 .fontColor(Color.White) 413 .groupDefaultFocus(true) // The button obtains focus when its upper-level column is in focus. 414 } 415 Row({ space: 5 }) { 416 Button() 417 .width(80) 418 .height(40) 419 .fontColor(Color.White) 420 Button() 421 .width(80) 422 .height(40) 423 .fontColor(Color.White) 424 } 425 }.borderWidth(2).borderColor(Color.Green).borderStyle(BorderStyle.Dashed) 426 .tabIndex(2) // The column is the second component to have focus in sequential keyboard navigation. 427 } 428 Column({ space: 5 }) { 429 TextInput({placeholder: 'input', text: this.inputValue}) 430 .onChange((value: string) => { 431 this.inputValue = value 432 }) 433 .width(156) 434 .defaultFocus(true) // The TextInput component is the initial default focus of the hierarchical page. 435 Button('Group3') 436 .width(165) 437 .height(40) 438 .fontColor(Color.White) 439 Row({ space: 5 }) { 440 Button() 441 .width(80) 442 .height(40) 443 .fontColor(Color.White) 444 Button() 445 .width(80) 446 .height(40) 447 .fontColor(Color.White) 448 } 449 Button() 450 .width(165) 451 .height(40) 452 .fontColor(Color.White) 453 Row({ space: 5 }) { 454 Button() 455 .width(80) 456 .height(40) 457 .fontColor(Color.White) 458 Button() 459 .width(80) 460 .height(40) 461 .fontColor(Color.White) 462 } 463 Button() 464 .width(165) 465 .height(40) 466 .fontColor(Color.White) 467 Row({ space: 5 }) { 468 Button() 469 .width(80) 470 .height(40) 471 .fontColor(Color.White) 472 Button() 473 .width(80) 474 .height(40) 475 .fontColor(Color.White) 476 } 477 }.borderWidth(2).borderColor(Color.Orange).borderStyle(BorderStyle.Dashed) 478 .tabIndex(3) // The column is the third component to have focus in sequential keyboard navigation. 479 }.alignItems(VerticalAlign.Top) 480 } 481 } 482} 483``` 484Diagrams: 485 486On first-time access, the focus is on the **TextInput** component bound to **defaultFocus**. 487 488 489 490Pressing the **Tab** key for the first time moves the focus to the container with **tabIndex(1)** and automatically navigates to the first focusable component inside the container. 491 492 493 494Pressing the **Tab** key a second time shifts the focus to the container with **tabIndex(2)** and automatically navigates to the component bound to **groupDefaultFocus**. 495 496 497 498Pressing the **Tab** key a third time shifts the focus to the container with **tabIndex(3)** and automatically navigates to the component bound to **DefaultFocus**. 499 500 501 502Clicking the component bound to **focusOnTouch** sets the focus on the component and removes the focus indicator. Pressing the **Tab** key again displays the focus indicator. 503 504 505 506### Example 2: Setting Focus on a Specific Component 507 508This example demonstrates how to set focus on a specific component using **focusControl.requestFocus**. 509 510> **NOTE** 511> 512> Directly using **focusControl** can lead to the issue of [ambiguous UI context](../../../ui/arkts-global-interface.md#ambiguous-ui-context). To avoid this, obtain a [UIContext](../js-apis-arkui-UIContext.md#uicontext) instance using **getUIContext()**, and then obtain the associated **focusControl** object using [getFocusController](../js-apis-arkui-UIContext.md#getfocuscontroller12). 513 514```ts 515// requestFocus.ets 516@Entry 517@Component 518struct RequestFocusExample { 519 @State idList: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'LastPageId']; 520 @State selectId: string = 'LastPageId'; 521 522 build() { 523 Column({ space:20 }){ 524 Row({space: 5}) { 525 Button("id: " + this.idList[0] + " focusable(false)") 526 .width(200).height(70).fontColor(Color.White) 527 .id(this.idList[0]) 528 .focusable(false) 529 Button("id: " + this.idList[1]) 530 .width(200).height(70).fontColor(Color.White) 531 .id(this.idList[1]) 532 } 533 Row({space: 5}) { 534 Button("id: " + this.idList[2]) 535 .width(200).height(70).fontColor(Color.White) 536 .id(this.idList[2]) 537 Button("id: " + this.idList[3]) 538 .width(200).height(70).fontColor(Color.White) 539 .id(this.idList[3]) 540 } 541 Row({space: 5}) { 542 Button("id: " + this.idList[4]) 543 .width(200).height(70).fontColor(Color.White) 544 .id(this.idList[4]) 545 Button("id: " + this.idList[5]) 546 .width(200).height(70).fontColor(Color.White) 547 .id(this.idList[5]) 548 } 549 Row({space: 5}) { 550 Select([{value: this.idList[0]}, 551 {value: this.idList[1]}, 552 {value: this.idList[2]}, 553 {value: this.idList[3]}, 554 {value: this.idList[4]}, 555 {value: this.idList[5]}, 556 {value: this.idList[6]}]) 557 .value(this.selectId) 558 .onSelect((index: number) => { 559 this.selectId = this.idList[index] 560 }) 561 Button("RequestFocus") 562 .width(200).height(70).fontColor(Color.White) 563 .onClick(() => { 564 // You are advised to use this.getUIContext().getFocusController().requestFocus(). 565 let res = focusControl.requestFocus(this.selectId) // Move the focus to the component specified by this.selectId. 566 if (res) { 567 this.getUIContext().getPromptAction().showToast({message: 'Request success'}) 568 } else { 569 this.getUIContext().getPromptAction().showToast({message: 'Request failed'}) 570 } 571 }) 572 } 573 }.width('100%').margin({ top:20 }) 574 } 575} 576``` 577 578Diagrams: 579 580Press the **Tab** key to activate the focus state. 581Below shows how the UI behaves when you request focus for a component that does not exist. 582 583 584 585Below shows how the UI behaves when you request focus for a component that is not focusable. 586 587 588 589Below shows how the UI behaves when you request focus for a focusable component. 590 591 592 593### Example 3: Customizing the Focus Box Style 594 595This example shows how to change the focus box style of a component by configuring **focusBox**. 596 597```ts 598import { ColorMetrics, LengthMetrics } from '@kit.ArkUI'; 599 600@Entry 601@Component 602struct RequestFocusExample { 603 build() { 604 Column({ space: 30 }) { 605 Button("small black focus box") 606 .focusBox({ 607 margin: new LengthMetrics(0), 608 strokeColor: ColorMetrics.rgba(0, 0, 0), 609 }) 610 Button("large red focus box") 611 .focusBox({ 612 margin: LengthMetrics.px(20), 613 strokeColor: ColorMetrics.rgba(255, 0, 0), 614 strokeWidth: LengthMetrics.px(10) 615 }) 616 } 617 .alignItems(HorizontalAlign.Center) 618 .width('100%') 619 } 620} 621``` 622 623 624 625 626### Example 4: Setting Focus Group Traversal 627 628This example demonstrates how to set a component as the initial focus when its container gains focus by configuring **focusScopePriority**. Configuring **focusScopeId** allows the bound container component to become a focus group. 629 630```ts 631// focusTest.ets 632@Entry 633@Component 634struct FocusableExample { 635 @State inputValue: string = ''; 636 637 build() { 638 Scroll() { 639 Row({ space: 20 }) { 640 Column({ space: 20 }) { // Labeled as Column1. 641 Column({ space: 5 }) { 642 Button('Group1') 643 .width(165) 644 .height(40) 645 .fontColor(Color.White) 646 Row({ space: 5 }) { 647 Button() 648 .width(80) 649 .height(40) 650 .fontColor(Color.White) 651 Button() 652 .width(80) 653 .height(40) 654 .fontColor(Color.White) 655 } 656 Row({ space: 5 }) { 657 Button() 658 .width(80) 659 .height(40) 660 .fontColor(Color.White) 661 Button() 662 .width(80) 663 .height(40) 664 .fontColor(Color.White) 665 } 666 }.borderWidth(2).borderColor(Color.Red).borderStyle(BorderStyle.Dashed) 667 Column({ space: 5 }) { 668 Button('Group2') 669 .width(165) 670 .height(40) 671 .fontColor(Color.White) 672 Row({ space: 5 }) { 673 Button() 674 .width(80) 675 .height(40) 676 .fontColor(Color.White) 677 Button() 678 .width(80) 679 .height(40) 680 .fontColor(Color.White) 681 .focusScopePriority('ColumnScope1', FocusPriority.PRIOR) // Focus when Column1 first gains focus. 682 } 683 Row({ space: 5 }) { 684 Button() 685 .width(80) 686 .height(40) 687 .fontColor(Color.White) 688 Button() 689 .width(80) 690 .height(40) 691 .fontColor(Color.White) 692 } 693 }.borderWidth(2).borderColor(Color.Green).borderStyle(BorderStyle.Dashed) 694 } 695 .focusScopeId('ColumnScope1') 696 Column({ space: 5 }) { // Labeled as Column2. 697 TextInput({placeholder: 'input', text: this.inputValue}) 698 .onChange((value: string) => { 699 this.inputValue = value 700 }) 701 .width(156) 702 Button('Group3') 703 .width(165) 704 .height(40) 705 .fontColor(Color.White) 706 Row({ space: 5 }) { 707 Button() 708 .width(80) 709 .height(40) 710 .fontColor(Color.White) 711 Button() 712 .width(80) 713 .height(40) 714 .fontColor(Color.White) 715 } 716 Button() 717 .width(165) 718 .height(40) 719 .fontColor(Color.White) 720 .focusScopePriority('ColumnScope2', FocusPriority.PREVIOUS) // Focuses when Column2 first gains focus. 721 Row({ space: 5 }) { 722 Button() 723 .width(80) 724 .height(40) 725 .fontColor(Color.White) 726 Button() 727 .width(80) 728 .height(40) 729 .fontColor(Color.White) 730 } 731 Button() 732 .width(165) 733 .height(40) 734 .fontColor(Color.White) 735 Row({ space: 5 }) { 736 Button() 737 .width(80) 738 .height(40) 739 .fontColor(Color.White) 740 Button() 741 .width(80) 742 .height(40) 743 .fontColor(Color.White) 744 } 745 }.borderWidth(2).borderColor(Color.Orange).borderStyle(BorderStyle.Dashed) 746 .focusScopeId('ColumnScope2', true) // Column2 is a focus group. 747 }.alignItems(VerticalAlign.Top) 748 } 749 } 750} 751``` 752Diagrams: 753 754Pressing the **Tab** key for the first time shifts the focus to the component bound to **focusScopePriority** in container 1. 755 756 757 758Pressing the **Tab** key again moves the focus to the next component in container 1. 759 760 761 762Pressing the **Tab** key once more shifts the focus to the subsequent component in container 1. 763 764 765 766Continuing to press the **Tab** key transfers the focus to the component configured with **focusScopePriority** in container 2. 767 768 769 770Pressing the **Tab** key again moves the focus to the component named **Group1** in container 1. 771 772 773 774### Example 5: Setting Focus Stop 775 776This example illustrates how to use **tabStop** to enable focus stop on a component during focus traversal with the **Tab** key. 777 778```ts 779import { ColorMetrics, LengthMetrics } from '@kit.ArkUI'; 780 781@Entry 782@Component 783struct TabStop { 784 build() { 785 Column({ space: 20 }) { 786 Column({ space: 20 }) { 787 Column({ space: 20 }) { 788 Row({ space: 5 }) { 789 Button("button 1") 790 .width(200).height(70).fontColor(Color.White) 791 .focusBox({ 792 margin: LengthMetrics.px(20), 793 strokeColor: ColorMetrics.rgba(23, 169, 141), 794 strokeWidth: LengthMetrics.px(10) 795 }) 796 } 797 Row({ space: 5 }) { 798 Button("button 2") 799 .width(200).height(70).fontColor(Color.White) 800 .focusBox({ 801 margin: LengthMetrics.px(20), 802 strokeColor: ColorMetrics.rgba(23, 169, 141), 803 strokeWidth: LengthMetrics.px(10) 804 }) 805 } 806 }.width('80%').margin({ top: 30 }).borderColor(Color.Black) 807 }.width('95%').margin({ top: 60 }).borderColor(Color.Black) 808 Column({ space: 20 }) { 809 Column({ space: 20 }) { 810 Row({ space: 5 }) { 811 Button("button 3") 812 .width(200) 813 .height('70%') 814 .fontColor(Color.White) 815 .focusBox({ 816 margin: LengthMetrics.px(20), 817 strokeColor: ColorMetrics.rgba(23, 169, 141), 818 strokeWidth: LengthMetrics.px(10) 819 }) 820 .margin({ top: 15 }) 821 } 822 } 823 .width('80%') 824 .height('120') 825 .borderColor(Color.Black) 826 .margin({ top: 10 }) 827 .tabStop(true) 828 .focusBox({ 829 margin: LengthMetrics.px(20), 830 strokeColor: ColorMetrics.rgba(23, 169, 141), 831 strokeWidth: LengthMetrics.px(10) 832 }) 833 .borderWidth(1) 834 }.width('95%').margin({ top: 50 }).borderColor(Color.Black) 835 } 836 } 837} 838``` 839Diagrams: 840 841Pressing **Tab** twice moves the focus to **button2**. 842 843 844 845Pressing **Tab** again moves the focus to the component configured with **tabStop**. 846 847 848 849Pressing **Enter** moves the focus to **button3**. 850 851 852 853Pressing **ESC** again moves the focus to the component configured with **tabStop**. 854 855 856 857Pressing **Tab** moves the focus back to **button1**. 858 859 860 861### Example 6: Setting Custom Focus Movement 862 863This example demonstrates how to implement custom focus movement logic using the **nextFocus** API. 864Without **nextFocus** configured, the default focus navigation order using the **Tab** key is as follows: M -> A -> B -> C. After **nextFocus** is configured, the order changes to the following: M -> D -> F -> B. 865 866```ts 867class MyButtonModifier implements AttributeModifier<ButtonAttribute> { 868 applyNormalAttribute(instance: ButtonAttribute): void { 869 instance.id('M') 870 instance.nextFocus({forward: 'D', up: 'C', down: 'D'}) 871 } 872} 873 874@Entry 875@Component 876struct Index { 877 @State modifier: MyButtonModifier = new MyButtonModifier(); 878 @State idList: string[] = ['A', 'B', 'C', 'D', 'E', 'F']; 879 880 build() { 881 Column({space: 10}) { 882 Row({space: 10}) { 883 Button("id: M") 884 .attributeModifier(this.modifier) 885 Button("id: " + this.idList[0]) 886 .id(this.idList[0]) 887 .nextFocus({forward: 'C', backward: 'M', up: 'E', right: 'F', down: 'B', left: 'D'}); 888 Button("id: " + this.idList[1]) 889 .id(this.idList[1]) 890 } 891 Column({space: 10}) { 892 Button("id: " + this.idList[2]) 893 .id(this.idList[2]); 894 Button("id: " + this.idList[3]) 895 .id(this.idList[3]) 896 .nextFocus({forward: 'F'}); 897 } 898 Row({space: 10}) { 899 Button("id: " + this.idList[4]) 900 .id(this.idList[4]); 901 Button("id: " + this.idList[5]) 902 .id(this.idList[5]) 903 .nextFocus({forward: 'B'}); 904 } 905 } 906 } 907} 908``` 909 910