• 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 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
10## Attributes
11
12| Name              | Type| Description                                  |
13| -------------------- | -------- | ---------------------------------------- |
14| focusable            | boolean  | Whether the current component is focusable.<br>**NOTE**<br>Components that have default interaction logic, such as **\<Button>** and **\<TextInput>**, are focusable by default. Other components, such as **\<Text>** and **\<Image>**, are not focusable by default. Only focusable components can trigger a [focus event](ts-universal-focus-event.md).|
15| tabIndex<sup>9+<sup> | number   | 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>- **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**|
16| defaultFocus<sup>9+<sup> | boolean  | Whether to set the component as the default focus of the page. This attribute takes effect only when the page is new and accessed for the first time.<br>Default value: **false**|
17| groupDefaultFocus<sup>9+<sup> | boolean  | 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>Default value: **false**<br>**NOTE**<br><br>This parameter must be used together with **tabIndex**. 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.|
18| focusOnTouch<sup>9+<sup> | boolean | Whether the component is focusable on touch.<br>Default value: **false**<br>**NOTE**<br>The component can obtain focus only when it is touchable or clickable.|
19
20## focusControl<sup>9+</sup>
21
22Implements focus control.
23
24### requestFocus<sup>9+</sup>
25
26requestFocus(value: string): boolean
27
28Requests the focus to move to the specified component. This API can be used in global method statements.
29
30**Parameters**
31
32| Name| Type| Mandatory| Description|
33| ----- | ------ | ---- | ---- |
34| value | string | Yes  | String bound to the target component using **key(value: string)** or **id(value: string)**.|
35
36**Return value**
37
38| Type| Description|
39| ------- | ---- |
40| boolean | Returns whether the focus is successfully moved to the target component. Returns **true** if the specified component exists and the focus is successfully moved to the target component; returns **false** otherwise.|
41
42>  **NOTE**
43>
44>  The following components support focus control: **\<TextInput>**, **\<TextArea>**, **\<Search>**, **\<Button>**, **\<Text>**, **\<Image>**, **\<List>**, and **\<Grid>**. Currently, the running effect of the focus event can be displayed only on a real device.
45
46## Example
47
48### Example 1
49
50This example shows how to use **defaultFocus**, **groupDefaultFocus**, and **focusOnTouch**.
51
52**defaultFocus** sets the bound component as the initial focus of the page after the page is created. **groupDefaultFocus** sets the bound component as the initial focus of the **tabIndex** container after the container is created. **focusOnTouch** sets the bound component to obtain focus upon being clicked.
53
54```ts
55// focusTest.ets
56@Entry
57@Component
58struct FocusableExample {
59  @State inputValue: string = ''
60
61  build() {
62    Scroll() {
63      Row({ space: 20 }) {
64        Column({ space: 20 }) {
65          Column({ space: 5 }) {
66            Button('Group1')
67              .width(165)
68              .height(40)
69              .fontColor(Color.White)
70              .focusOnTouch(true)           // The button is focusable on touch.
71            Row({ space: 5 }) {
72              Button()
73                .width(80)
74                .height(40)
75                .fontColor(Color.White)
76              Button()
77                .width(80)
78                .height(40)
79                .fontColor(Color.White)
80                .focusOnTouch(true)           // The button is focusable on touch.
81            }
82            Row({ space: 5 }) {
83              Button()
84                .width(80)
85                .height(40)
86                .fontColor(Color.White)
87              Button()
88                .width(80)
89                .height(40)
90                .fontColor(Color.White)
91            }
92          }.borderWidth(2).borderColor(Color.Red).borderStyle(BorderStyle.Dashed)
93          .tabIndex(1)                      // The column is the initial component to have focus in sequential keyboard navigation.
94          Column({ space: 5 }) {
95            Button('Group2')
96              .width(165)
97              .height(40)
98              .fontColor(Color.White)
99            Row({ space: 5 }) {
100              Button()
101                .width(80)
102                .height(40)
103                .fontColor(Color.White)
104              Button()
105                .width(80)
106                .height(40)
107                .fontColor(Color.White)
108                .groupDefaultFocus(true)      // The button obtains focus when its upper-level column is in focus.
109            }
110            Row({ space: 5 }) {
111              Button()
112                .width(80)
113                .height(40)
114                .fontColor(Color.White)
115              Button()
116                .width(80)
117                .height(40)
118                .fontColor(Color.White)
119            }
120          }.borderWidth(2).borderColor(Color.Green).borderStyle(BorderStyle.Dashed)
121          .tabIndex(2)                      // The column is the second component to have focus in sequential keyboard navigation.
122        }
123        Column({ space: 5 }) {
124          TextInput({placeholder: 'input', text: this.inputValue})
125            .onChange((value: string) => {
126              this.inputValue = value
127            })
128            .width(156)
129            .defaultFocus(true)             // The <TextInput> component is the initial default focus of the page.
130          Button('Group3')
131            .width(165)
132            .height(40)
133            .fontColor(Color.White)
134          Row({ space: 5 }) {
135            Button()
136              .width(80)
137              .height(40)
138              .fontColor(Color.White)
139            Button()
140              .width(80)
141              .height(40)
142              .fontColor(Color.White)
143          }
144          Button()
145            .width(165)
146            .height(40)
147            .fontColor(Color.White)
148          Row({ space: 5 }) {
149            Button()
150              .width(80)
151              .height(40)
152              .fontColor(Color.White)
153            Button()
154              .width(80)
155              .height(40)
156              .fontColor(Color.White)
157          }
158          Button()
159            .width(165)
160            .height(40)
161            .fontColor(Color.White)
162          Row({ space: 5 }) {
163            Button()
164              .width(80)
165              .height(40)
166              .fontColor(Color.White)
167            Button()
168              .width(80)
169              .height(40)
170              .fontColor(Color.White)
171          }
172        }.borderWidth(2).borderColor(Color.Orange).borderStyle(BorderStyle.Dashed)
173        .tabIndex(3)                      // The column is the third component to have focus in sequential keyboard navigation.
174      }.alignItems(VerticalAlign.Top)
175    }
176  }
177}
178```
179Diagrams:
180
181When you press the **Tab** key for the first time, the focus switches to the component bound to **defaultFocus**.
182
183![defaultFocus](figures/defaultFocus.png)
184
185When you press the **Tab** key for the second time, the focus switches to the container that matches **tabIndex(1)** and automatically moves to the component bound to **groupDefaultFocus**.
186
187![groupDefaultFocus1](figures/groupDefaultFocus1.png)
188
189When you press the **Tab** key for the third time, the focus switches to the container that matches **tabIndex(2)** and automatically moves to the component bound to **groupDefaultFocus**.
190
191![groupDefaultFocus2](figures/groupDefaultFocus2.png)
192
193When you press the **Tab** key for the fourth time, the focus switches to the container that matches **tabIndex(3)** and automatically moves to the component bound to **groupDefaultFocus**.
194
195![groupDefaultFocus3](figures/groupDefaultFocus3.png)
196
197Click the component bound to **focusOnTouch**. The component then obtains focus.
198
199![focusOnTouch](figures/focusOnTouch.png)
200
201### Example 2
202
203This example shows how to use **focusControl.requestFocus** to move the focus to the specified component.
204
205```ts
206// requestFocus.ets
207import promptAction from '@ohos.promptAction';
208
209@Entry
210@Component
211struct RequestFocusExample {
212  @State idList: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'LastPageId']
213  @State selectId: string = 'LastPageId'
214
215  build() {
216    Column({ space:20 }){
217      Row({space: 5}) {
218        Button("id: " + this.idList[0] + " focusable(false)")
219          .width(200).height(70).fontColor(Color.White)
220          .id(this.idList[0])
221          .focusable(false)
222        Button("id: " + this.idList[1])
223          .width(200).height(70).fontColor(Color.White)
224          .id(this.idList[1])
225      }
226      Row({space: 5}) {
227        Button("id: " + this.idList[2])
228          .width(200).height(70).fontColor(Color.White)
229          .id(this.idList[2])
230        Button("id: " + this.idList[3])
231          .width(200).height(70).fontColor(Color.White)
232          .id(this.idList[3])
233      }
234      Row({space: 5}) {
235        Button("id: " + this.idList[4])
236          .width(200).height(70).fontColor(Color.White)
237          .id(this.idList[4])
238        Button("id: " + this.idList[5])
239          .width(200).height(70).fontColor(Color.White)
240          .id(this.idList[5])
241      }
242      Row({space: 5}) {
243        Select([{value: this.idList[0]},
244                {value: this.idList[1]},
245                {value: this.idList[2]},
246                {value: this.idList[3]},
247                {value: this.idList[4]},
248                {value: this.idList[5]},
249                {value: this.idList[6]}])
250          .value(this.selectId)
251          .onSelect((index: number) => {
252            this.selectId = this.idList[index]
253          })
254        Button("RequestFocus")
255          .width(200).height(70).fontColor(Color.White)
256          .onClick(() => {
257            let res = focusControl.requestFocus(this.selectId)      // Move the focus to the component specified by this.selectId.
258            if (res) {
259              promptAction.showToast({message: 'Request success'})
260            } else {
261              promptAction.showToast({message: 'Request failed'})
262            }
263          })
264      }
265    }.width('100%').margin({ top:20 })
266  }
267}
268```
269
270Diagrams:
271
272Press the **Tab** key to activate the focus state.
273
274Below shows how the UI behaves when you request focus for a component that does not exist.
275
276![requestFocus1](figures/requestFocus1.png)
277
278Below shows how the UI behaves when you request focus for a component that is not focusable.
279
280![requestFocus2](figures/requestFocus2.png)
281
282Below shows how the UI behaves when you request focus for a focusable component.
283
284![requestFocus3](figures/requestFocus3.png)
285