• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 焦点控制
2
3自定义组件的走焦效果,可设置组件是否走焦和具体的走焦顺序,tab键或者方向键切换焦点。
4
5>  **说明:**
6>
7>  从API Version 8开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
8
9
10## 属性
11
12| **名称**               | **参数类型** | **描述**                                   |
13| -------------------- | -------- | ---------------------------------------- |
14| focusable            | boolean  | 设置当前组件是否可以获焦。<br/>**说明:**<br/>存在默认交互逻辑的组件例如Button、TextInput等,默认即为可获焦,Text、Image等组件则默认状态为不可获焦。不可获焦状态下,无法触发[焦点事件](ts-universal-focus-event.md)。 |
15| tabIndex<sup>9+<sup> | number   | 自定义组件tab键走焦能力。若有配置了tabIndex大于0的组件,则tab键走焦只会在tabIndex大于0的组件内按照tabIndex的值从小到大并循环依次走焦。若没有配置tabIndex大于0的组件,则tabIndex等于0的组件按照组件预设的走焦规则走焦。<br />- tabIndex >= 0:表示元素是可聚焦的,并且可以通过tab键走焦来访问到该元素。<br />- tabIndex < 0(通常是tabIndex = -1):表示元素是可聚焦的,但是不能通过tab键走焦来访问到该元素。<br/>默认值:0 |
16| defaultFocus<sup>9+<sup> | boolean  | 设置当前组件是否为当前页面上的默认焦点,仅在初次创建的页面第一次进入时生效。<br/>默认值:false<br/>**说明:** 值为true则表示为默认焦点,值为false无效。<br/>若页面内无任何组件设置defaultFocus(true),页面的默认焦点就是页面的根容器。<br/>若某页面内有多个组件设置了defaultFocus(true),则以组件树深度遍历找到的第一个组件为默认焦点。 |
17| groupDefaultFocus<sup>9+<sup> | boolean  | 设置当前组件是否为当前组件所在容器获焦时的默认焦点,仅在初次创建容器节点第一次获焦时生效。<br/>默认值:false<br/>**说明:** 必须与tabIndex联合使用,当某个容器设置了tabIndex,且容器内某子组件或容器自身设置了groupDefaultFocus(true),当该容器首次TAB键获焦时,会自动将焦点转移至该指定的组件上。若容器内(包含容器本身)有多个组件设置了groupDefaultFocus(true),则以组件树深度遍历找到的第一个组件为最终结果。 |
18| focusOnTouch<sup>9+<sup> | boolean | 设置当前组件是否支持点击获焦能力。<br/>默认值:false<br/>**说明:** 仅在组件可点击时才能正常获取焦点。 |
19
20## focusControl<sup>9+</sup>
21
22焦点控制模块
23
24### requestFocus<sup>9+</sup>
25
26requestFocus(value: string): boolean
27
28方法语句中可使用的全局接口,调用此接口可以主动让焦点转移至参数指定的组件上。
29
30**参数:**
31
32| 名称 | 类型 | 必填 | 描述 |
33| ----- | ------ | ---- | ---- |
34| value | string | 是   | 目标组件使用接口key(value: string)或id(value: string)绑定的字符串。 |
35
36**返回值:**
37
38| 类型 | 说明 |
39| ------- | ---- |
40| boolean | 返回是否成功给目标组件申请到焦点。若参数指向的目标组件存在,且目标组件可获焦,则返回true,否则返回false。 |
41
42>  **说明:**
43>
44>  支持焦点控制的组件:TextInput、TextArea、Search、Button、Text、Image、List、Grid。焦点事件当前仅支持在真机上显示运行效果。
45
46## 示例
47
48### 示例1
49
50defaultFocus/groupDefaultFocus/focusOnTouch示例代码:
51
52defaultFocus可以使绑定的组件成为页面创建后首次获焦的焦点。groupDefaultFocus可以使绑定的组件成为tabIndex容器创建后首次获焦的焦点。focusOnTouch可以使绑定的组件点击后立即获焦。
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)           // 该Button组件点击后可获焦
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)           // 该Button组件点击后可获焦
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)                      // 该Column组件为按TAB键走焦的第一个获焦的组件
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)      // 该Button组件上级Column组件获焦时获焦
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)                      // 该Column组件为按TAB键走焦的第二个获焦的组件
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)             // 该TextInput组件为页面的初始默认焦点
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)                      // 该Column组件为按TAB键走焦的第三个获焦的组件
174      }.alignItems(VerticalAlign.Top)
175    }
176  }
177}
178```
179示意图:
180
181首次按下TAB键,焦点切换到defaultFocus绑定的组件上:
182
183![defaultFocus](figures/defaultFocus.png)
184
185第二次按TAB键,焦点切换到tabIndex(1)的容器上,且自动走到其内部的groupDefaultFocus绑定的组件上:
186
187![groupDefaultFocus1](figures/groupDefaultFocus1.png)
188
189第三次按TAB键,焦点切换到tabIndex(2)的容器上,且自动走到其内部的groupDefaultFocus绑定的组件上:
190
191![groupDefaultFocus2](figures/groupDefaultFocus2.png)
192
193第四次按TAB键,焦点切换到tabIndex(3)的容器上,且自动走到其内部的groupDefaultFocus绑定的组件上:
194
195![groupDefaultFocus3](figures/groupDefaultFocus3.png)
196
197点击绑定了focusOnTouch的组件,组件自身获焦:
198
199![focusOnTouch](figures/focusOnTouch.png)
200
201### 示例2
202
203focusControl.requestFocus示例代码:
204
205使用focusContrl.requestFocus接口使指定组件获取焦点。
206```ts
207// requestFocus.ets
208import promptAction from '@ohos.promptAction';
209
210@Entry
211@Component
212struct RequestFocusExample {
213  @State idList: string[] = ['A', 'B', 'C', 'D', 'E', 'F', 'LastPageId']
214  @State selectId: string = 'LastPageId'
215
216  build() {
217    Column({ space:20 }){
218      Row({space: 5}) {
219        Button("id: " + this.idList[0] + " focusable(false)")
220          .width(200).height(70).fontColor(Color.White)
221          .id(this.idList[0])
222          .focusable(false)
223        Button("id: " + this.idList[1])
224          .width(200).height(70).fontColor(Color.White)
225          .id(this.idList[1])
226      }
227      Row({space: 5}) {
228        Button("id: " + this.idList[2])
229          .width(200).height(70).fontColor(Color.White)
230          .id(this.idList[2])
231        Button("id: " + this.idList[3])
232          .width(200).height(70).fontColor(Color.White)
233          .id(this.idList[3])
234      }
235      Row({space: 5}) {
236        Button("id: " + this.idList[4])
237          .width(200).height(70).fontColor(Color.White)
238          .id(this.idList[4])
239        Button("id: " + this.idList[5])
240          .width(200).height(70).fontColor(Color.White)
241          .id(this.idList[5])
242      }
243      Row({space: 5}) {
244        Select([{value: this.idList[0]},
245                {value: this.idList[1]},
246                {value: this.idList[2]},
247                {value: this.idList[3]},
248                {value: this.idList[4]},
249                {value: this.idList[5]},
250                {value: this.idList[6]}])
251          .value(this.selectId)
252          .onSelect((index: number) => {
253            this.selectId = this.idList[index]
254          })
255        Button("RequestFocus")
256          .width(200).height(70).fontColor(Color.White)
257          .onClick(() => {
258            let res = focusControl.requestFocus(this.selectId)      // 使选中的this.selectId的组件获焦
259            if (res) {
260              promptAction.showToast({message: 'Request success'})
261            } else {
262              promptAction.showToast({message: 'Request failed'})
263            }
264          })
265      }
266    }.width('100%').margin({ top:20 })
267  }
268}
269```
270
271示意图:
272
273按下TAB键,激活焦点态显示。
274申请不存在的组件获焦:
275
276![requestFocus1](figures/requestFocus1.png)
277
278申请不可获焦的组件获焦:
279
280![requestFocus2](figures/requestFocus2.png)
281
282申请存在且可获焦的组件获焦:
283
284![requestFocus3](figures/requestFocus3.png)