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