• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Focus Control
2
3Focus control attributes set whether a component is focusable, how it participates in sequential keyboard 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, their focus order follows their position 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 current 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 current component as the default focus of the parent container. This attribute takes effect only when the container is new and has 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 the focus for the first time.|
18| focusOnTouch<sup>9+</sup> | boolean | Whether the current 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
48defaultFocus/groupDefaultFocus/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```ts
52// focusTest.ets
53@Entry
54@Component
55struct FocusableExample {
56  @State inputValue: string = ''
57
58  build() {
59    Scroll() {
60      Row({ space: 20 }) {
61        Column({ space: 20 }) {
62          Column({ space: 5 }) {
63            Button('Group1')
64              .width(165)
65              .height(40)
66              .fontColor(Color.White)
67              .focusOnTouch(true)           // The button is focusable on touch.
68            Row({ space: 5 }) {
69              Button()
70                .width(80)
71                .height(40)
72                .fontColor(Color.White)
73              Button()
74                .width(80)
75                .height(40)
76                .fontColor(Color.White)
77                .focusOnTouch(true)           // The button is focusable on touch.
78            }
79            Row({ space: 5 }) {
80              Button()
81                .width(80)
82                .height(40)
83                .fontColor(Color.White)
84              Button()
85                .width(80)
86                .height(40)
87                .fontColor(Color.White)
88            }
89          }.borderWidth(2).borderColor(Color.Red).borderStyle(BorderStyle.Dashed)
90          .tabIndex(1)                      // The column is the initial component to have focus in sequential keyboard navigation.
91          Column({ space: 5 }) {
92            Button('Group2')
93              .width(165)
94              .height(40)
95              .fontColor(Color.White)
96            Row({ space: 5 }) {
97              Button()
98                .width(80)
99                .height(40)
100                .fontColor(Color.White)
101              Button()
102                .width(80)
103                .height(40)
104                .fontColor(Color.White)
105                .groupDefaultFocus(true)      // The button obtains focus when its upper-level column is in focus.
106            }
107            Row({ space: 5 }) {
108              Button()
109                .width(80)
110                .height(40)
111                .fontColor(Color.White)
112              Button()
113                .width(80)
114                .height(40)
115                .fontColor(Color.White)
116            }
117          }.borderWidth(2).borderColor(Color.Green).borderStyle(BorderStyle.Dashed)
118          .tabIndex(2)                      // The column is the second component to have focus in sequential keyboard navigation.
119        }
120        Column({ space: 5 }) {
121          TextInput({placeholder: 'input', text: this.inputValue})
122            .onChange((value: string) => {
123              this.inputValue = value
124            })
125            .defaultFocus(true)             // The <TextInput> component is the initial default focus of the page.
126          Button('Group3')
127            .width(165)
128            .height(40)
129            .fontColor(Color.White)
130          Row({ space: 5 }) {
131            Button()
132              .width(80)
133              .height(40)
134              .fontColor(Color.White)
135            Button()
136              .width(80)
137              .height(40)
138              .fontColor(Color.White)
139          }
140          Button()
141            .width(165)
142            .height(40)
143            .fontColor(Color.White)
144          Row({ space: 5 }) {
145            Button()
146              .width(80)
147              .height(40)
148              .fontColor(Color.White)
149            Button()
150              .width(80)
151              .height(40)
152              .fontColor(Color.White)
153          }
154          Button()
155            .width(165)
156            .height(40)
157            .fontColor(Color.White)
158          Row({ space: 5 }) {
159            Button()
160              .width(80)
161              .height(40)
162              .fontColor(Color.White)
163            Button()
164              .width(80)
165              .height(40)
166              .fontColor(Color.White)
167          }
168        }.borderWidth(2).borderColor(Color.Orange).borderStyle(BorderStyle.Dashed)
169        .tabIndex(3)                      // The column is the third component to have focus in sequential keyboard navigation.
170      }.alignItems(VerticalAlign.Top)
171    }
172  }
173}
174```
175Diagrams:
176
177When you press the Tab button for the first time, the focus switches to the component bound to **defaultFocus**.
178
179![defaultFocus](figures/defaultFocus.png)
180
181When 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**.
182
183![groupDefaultFocus1](figures/groupDefaultFocus1.png)
184
185When 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**.
186
187![groupDefaultFocus2](figures/groupDefaultFocus2.png)
188
189When 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**.
190
191![groupDefaultFocus3](figures/groupDefaultFocus3.png)
192
193Click the component bound to **focusOnTouch**. The component then obtains the focus.
194
195![focusOnTouch](figures/focusOnTouch.png)
196
197### Example 2
198
199Sample code for **focusControl.requestFocus**:
200
201Use the **focusContrl.requestFocus** API to enable a specified component to obtain focus.
202```ts
203// requestFocus.ets
204import prompt from '@ohos.prompt'
205
206@Entry
207@Component
208struct RequestFocusExample {
209  @State idList: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'LastPageId']
210  @State selectId: string = 'LastPageId'
211
212  build() {
213    Column({ space:20 }){
214      Row({space: 5}) {
215        Button("id: " + this.idList[0] + " focusable(false)")
216          .width(200).height(70).fontColor(Color.White)
217          .key(this.idList[0])
218          .focusable(false)
219        Button("id: " + this.idList[1])
220          .width(200).height(70).fontColor(Color.White)
221          .key(this.idList[1])
222      }
223      Row({space: 5}) {
224        Button("id: " + this.idList[2])
225          .width(200).height(70).fontColor(Color.White)
226          .key(this.idList[2])
227        Button("id: " + this.idList[3])
228          .width(200).height(70).fontColor(Color.White)
229          .key(this.idList[3])
230      }
231      Row({space: 5}) {
232        Button("id: " + this.idList[4])
233          .width(200).height(70).fontColor(Color.White)
234          .key(this.idList[4])
235        Button("id: " + this.idList[5])
236          .width(200).height(70).fontColor(Color.White)
237          .key(this.idList[5])
238      }
239      Row({space: 5}) {
240        Select([{value: this.idList[0]},
241                {value: this.idList[1]},
242                {value: this.idList[2]},
243                {value: this.idList[3]},
244                {value: this.idList[4]},
245                {value: this.idList[5]},
246                {value: this.idList[6]}])
247          .value(this.selectId)
248          .onSelect((index: number) => {
249            this.selectId = this.idList[index]
250          })
251        Button("RequestFocus")
252          .width(200).height(70).fontColor(Color.White)
253          .onClick(() => {
254            var res = focusControl.requestFocus(this.selectId)      // Enable the component selected by this.selectId to obtain focus.
255            if (res) {
256              prompt.showToast({message: 'Request success'})
257            } else {
258              prompt.showToast({message: 'Request failed'})
259            }
260          })
261      }
262    }.width('100%').margin({ top:20 })
263  }
264}
265```
266
267Diagrams:
268
269Press the Tab button to activate the focus state.
270
271Below shows how the UI behaves when you request focus for a component that does not exist.
272
273![requestFocus1](figures/requestFocus1.png)
274
275Below shows how the UI behaves when you request focus for a component that is not focusable.
276
277![requestFocus2](figures/requestFocus2.png)
278
279Below shows how the UI behaves when you request focus for a focusable component.
280
281![requestFocus3](figures/requestFocus3.png)
282