• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![tabStop](figures/tabStop.png)
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![defaultFocus](figures/defaultFocus.png)
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![groupDefaultFocus1](figures/groupDefaultFocus1.png)
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![groupDefaultFocus2](figures/groupDefaultFocus2.png)
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![groupDefaultFocus3](figures/groupDefaultFocus3.png)
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![focusOnTouch](figures/focusOnTouch.png)
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![requestFocus1](figures/requestFocus1.png)
584
585Below shows how the UI behaves when you request focus for a component that is not focusable.
586
587![requestFocus2](figures/requestFocus2.png)
588
589Below shows how the UI behaves when you request focus for a focusable component.
590
591![requestFocus3](figures/requestFocus3.png)
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![focusBox](figures/focusBox.gif)
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![focusScopePriority1](figures/focusScopePriority1.png)
757
758Pressing the **Tab** key again moves the focus to the next component in container 1.
759
760![focusScopePriority2](figures/focusScopePriority2.png)
761
762Pressing the **Tab** key once more shifts the focus to the subsequent component in container 1.
763
764![focusScopePriority3](figures/focusScopePriority3.png)
765
766Continuing to press the **Tab** key transfers the focus to the component configured with **focusScopePriority** in container 2.
767
768![focusScopePriority4](figures/focusScopePriority4.png)
769
770Pressing the **Tab** key again moves the focus to the component named **Group1** in container 1.
771
772![focusScopePriority5](figures/focusScopePriority5.png)
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![tabStop2](figures/tabStop2.png)
844
845Pressing **Tab** again moves the focus to the component configured with **tabStop**.
846
847![tabStop3](figures/tabStop3.png)
848
849Pressing **Enter** moves the focus to **button3**.
850
851![tabStop4](figures/tabStop4.png)
852
853Pressing **ESC** again moves the focus to the component configured with **tabStop**.
854
855![tabStop3](figures/tabStop3.png)
856
857Pressing **Tab** moves the focus back to **button1**.
858
859![tabStop1](figures/tabStop1.png)
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![focusBox](figures/nextStep.gif)
910