• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Web组件对接软键盘
2<!--Kit: ArkWeb-->
3<!--Subsystem: Web-->
4<!--Owner: @weixin_41848015-->
5<!--Designer: @libing23232323-->
6<!--Tester: @ghiker-->
7<!--Adviser: @HelloCrease-->
8
9开发者能够通过Web组件对接软键盘,来处理系统软键盘的显示与交互问题,同时实现软键盘的自定义功能。主要有以下场景:
10
11- 拉起系统软键盘输入文字:点击网页输入框时,屏幕下方将弹出系统默认的软键盘。开发者可以通过软键盘输入文字,输入的内容会显示在输入框中。
12- 自定义系统软键盘的回车键类型:设置不同的回车键类型,例如:确认、下一个和提交。
13- 软键盘避让:在移动设备上,由于输入法通常固定在屏幕下半段,应用可设置不同的Web页面软键盘避让模式,来避让软键盘。例如:平移、调整大小和不避让。
14- 自定义软键盘输入:在移动设备上,可以使用自绘制输入法在Web页面输入,以此替代系统软键盘。
15
16
17
18## Web页面输入框输入与软键盘交互的W3C标准支持
19
20为支持Web页面与系统软键盘、自定义软键盘等的良好交互,ArkWeb遵循并实现了W3C规范中的以下输入控制属性:
21- type属性
22
23  type属性定义了input元素的类型,影响输入的验证、显示方式和键盘类型。常见的type值包括:
24
25  | type值    | 描述         |
26  | -------- | ---------- |
27  | text     | 默认值。普通文本输入 |
28  | number   | 数字输入       |
29  | email    | 电子邮件地址输入   |
30  | password | 密码输入       |
31  | tel      | 电话号码输入     |
32  | url      | URL输入      |
33  | date     | 日期选择器      |
34  | time     | 时间选择器      |
35  | checkbox | 复选框        |
36  | radio    | 单选按钮       |
37  | file     | 文件上传       |
38  | submit   | 提交按钮       |
39  | reset    | 重置按钮       |
40  | button   | 普通按钮       |
41
42- inputmode属性
43
44  inputmode属性用于配置输入法类型,默认值:text。
45
46  | inputmode | 描述                                       |
47  | --------- | ---------------------------------------- |
48  | decimal   | 只显示数字键盘,通常还有一个逗号键。                        |
49  | email     | 文本键盘,键通常用于电子邮件地址,如[@]。                   |
50  | none      | 不应出现键盘。                                   |
51  | numeric   | 只显示数字键盘。                                  |
52  | search    | 文本键盘,[enter]键通常显示为[go]。                   |
53  | tel       | 只显示数字键盘,通常还有[+]、[*]和[#]键。                |
54  | text      | 默认文本键盘。                                  |
55  | url       | 文本键盘,键通常用于网址,如[.]和[/],以及特殊的[.com]键,或者其他通常用于本地设置的域名结束符。 |
56
57- enterkeyhint属性
58
59  enterkeyhint属性用于指定移动设备虚拟键盘上回车键的显示方式。
60
61  | enterkeyhint值 | 描述        |
62  | ------------- | --------- |
63  | enter         | 显示默认的回车键  |
64  | done          | 表示输入完成    |
65  | go            | 表示跳转或执行   |
66  | next          | 进入下一个输入字段 |
67  | previous      | 返回上一个输入字段 |
68  | search        | 执行搜索      |
69  | send          | 发送信息      |
70
71>**说明:**
72>
73>点击网页输入框时,屏幕下方将弹出系统默认的软键盘,用户可以进行文字输入。
74>
75>type属性影响键盘显示、输入验证和元素外观。
76>
77>inputmode优化移动设备键盘输入体验,不影响基本行为或验证。
78
79
80## 软键盘自动弹出
81为提升用户体验,可以在页面完成加载后,输入框自动获焦并弹出软键盘。通过调用[showTextInput()](../reference/apis-ime-kit/js-apis-inputmethod.md#showtextinput10)设置软键盘自动弹出功能。
82
83```html
84<!-- index.html -->
85<!DOCTYPE html>
86<html>
87  <head>
88    <title>测试网页</title>
89  </head>
90  <body>
91    <h1>DEMO</h1>
92    <input type="text" id="input_a">
93  </body>
94</html>
95```
96
97```ts
98//Index.ets
99import { webview } from '@kit.ArkWeb';
100import { inputMethod } from '@kit.IMEKit';
101
102@Entry
103@Component
104struct WebComponent {
105  controller: webview.WebviewController = new webview.WebviewController();
106  build() {
107    Column() {
108      Web({ src: $rawfile("index.html"), controller: this.controller})
109        .onPageEnd(() => {
110          this.controller.runJavaScript(`document.getElementById('input_a').focus()`).then(() => {
111            setTimeout(() => {
112              inputMethod.getController().showTextInput();
113            }, 10);
114          });
115        });
116    }
117  }
118}
119```
120
121## 设置软键盘避让模式
122
123在移动设备上,支持设置Web页面的软键盘避让模式。
124
1251. 在应用代码中设置UIContext的软键盘避让模式[setKeyboardAvoidMode()](../reference/apis-arkui/arkui-ts/ts-universal-attributes-expand-safe-area.md#setkeyboardavoidmode11)。ArkWeb组件支持Resize和Offset两种模式。
126
127- Resize模式下,应用窗口高度可缩小避开软键盘,ArkWeb组件跟随ArkUI重新布局。
128- Offset模式下(以及默认模式),应用窗口高度不变,ArkWeb组件根据自身的避让模式进行避让。
129
130(1)设置UIContext的软键盘避让模式。
131
132```ts
133// EntryAbility.ets
134import { KeyboardAvoidMode } from '@kit.ArkUI';
135import { hilog } from '@kit.PerformanceAnalysisKit';
136
137onWindowStageCreate(windowStage: window.WindowStage) {
138  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
139
140  windowStage.loadContent('pages/Index', (err, data) => {
141    let keyboardAvoidMode = windowStage.getMainWindowSync().getUIContext().getKeyboardAvoidMode();
142    // 设置虚拟键盘抬起时压缩页面大小为减去键盘的高度
143  windowStage.getMainWindowSync().getUIContext().setKeyboardAvoidMode(KeyboardAvoidMode.RESIZE);
144    if (err.code) {
145      hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
146      return;
147    }
148    hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
149  });
150}
151```
152(2)在Web组件中调起软键盘。
153
154```html
155<!-- index.html -->
156<!DOCTYPE html>
157<html>
158  <head>
159    <title>测试网页</title>
160  </head>
161  <body>
162    <h1>DEMO</h1>
163    <input type="text" id="input_a">
164  </body>
165</html>
166```
167
168```ts
169//Index.ets
170import { webview } from '@kit.ArkWeb';
171
172@Entry
173@Component
174struct KeyboardAvoidExample {
175  controller: webview.WebviewController = new webview.WebviewController();
176  build() {
177    Column() {
178      Row().height("50%").width("100%").backgroundColor(Color.Gray)
179      Web({ src: $rawfile("index.html"),controller: this.controller})
180      Text("I can see the bottom of the page").width("100%").textAlign(TextAlign.Center).backgroundColor(Color.Pink).layoutWeight(1)
181    }.width('100%').height("100%")
182  }
183}
184```
185ArkWeb组件将跟随ArkUI重新布局,效果如图1和图2所示。
186
187**图1**  Web组件网页默认软键盘避让模式
188
189![default-keyboardavoid](figures/default-keyboardavoid.png)
190
191**图2**  Web组件网页跟随Arkui软键盘避让模式
192
193![arkui-keyboardavoid](figures/arkui-keyboardavoid.png)
194
1952.在UIContext的键盘避让模式为Offset模式时,应用可通过[WebKeyboardAvoidMode()](../reference/apis-arkweb/arkts-basic-components-web-e.md#webkeyboardavoidmode12)设置ArkWeb组件的键盘避让模式。Web组件的[WebKeyboardAvoidMode()](../reference/apis-arkweb/arkts-basic-components-web-e.md#webkeyboardavoidmode12)接口优先级高于W3C侧virtualKeyboard.overlayContens196
197- RESIZE_VISUAL:仅调整可视视口的大小,而不调整布局视口的大小。
198- RESIZE_CONTENT:调整视觉视口和布局视口的大小。
199- OVERLAYS_CONTENT:不调整任何视口的大小,获焦input元素没有滚动到可识区域的行为。
200
201>**说明:**
202>
203>可视视口指用户正在看到的网站的区域,该区域的宽度等于移动设备的浏览器窗口的宽度。
204>
205>布局视口指网页本身的宽度。
206
207在应用代码中设置ArkWeb的软键盘避让模式。
208
209```ts
210// Index.ets
211import { webview } from '@kit.ArkWeb';
212
213@Entry
214@Component
215struct KeyboardAvoidExample {
216  controller: webview.WebviewController = new webview.WebviewController();
217  build() {
218    Column() {
219      Row().height("50%").width("100%").backgroundColor(Color.Gray)
220      Web({ src: $rawfile("index.html"),controller: this.controller})
221        .keyboardAvoidMode(WebKeyboardAvoidMode.OVERLAYS_CONTENT) //此时ArkWeb组件不会调整任何视口的大小。
222      Text("I can see the bottom of the page").width("100%").textAlign(TextAlign.Center).backgroundColor(Color.Pink).layoutWeight(1)
223    }.width('100%').height("100%")
224  }
225}
226```
227ArkWeb组件根据避让模式进行避让,效果见图3。
228
229**图3**  Web组件网页自身软键盘避让模式
230
231![web-keyboardavoid](figures/web-keyboardavoid.png)
232
2333.在软键盘弹出时,为使Web组件不发生避让行为,可通过调用[expandSafeArea()](../reference/apis-arkui/arkui-ts/ts-universal-attributes-expand-safe-area.md#expandsafearea)设置Web组件扩展安全区域。更多详细示例可参考[网页中安全区域计算和避让适配](../web/web-safe-area-insets.md)。
234
235  ```ts
236  // xxx.ets
237  import { webview } from '@kit.ArkWeb';
238
239  @Entry
240  @Component
241  struct WebComponent {
242    controller: webview.WebviewController = new webview.WebviewController();
243
244    build() {
245      Column() {
246        Web({ src: 'www.example.com', controller: this.controller })
247          .width('100%').height('100%')
248          .expandSafeArea([SafeAreaType.KEYBOARD, SafeAreaType.SYSTEM])
249      }
250    }
251  }
252  ```
253
254
255与其他Web组件行为的交互场景:
256
257| 交叉场景         | 规格                                       |
258| ------------ | ---------------------------------------- |
259| 同层渲染         | 同层Web:软键盘避让方式与普通场景相同。<br></div>同层系统组件:由ArkUI负责软键盘避让模式。 |
260| 离屏创建组件       | 默认使用与非离屏创建一致的软键盘避让模式 在上树前设置其他避让模式可需生效。   |
261| customDialog | customDialog自身避让。                        |
262| 折叠屏          | 软键盘避让行为与普通场景行为一致。软件键盘将根据屏幕开合状态进行调整。    |
263| 软键盘托管        | 软键盘避让行为与普通场景行为一致。                        |
264| Web嵌套滚动      | 在嵌套滚动场景下,建议不要使用Web软键盘避让,包括RESIZE_VISUAL和RESIZE_CONTENT。 |
265
266
267
268## 拦截系统软键盘与自定义软键盘输入
269
270应用可以通过调用[onInterceptKeyboardAttach](../reference/apis-arkweb/arkts-basic-components-web-events.md#oninterceptkeyboardattach12)标签即将触发软键盘显示时,[onInterceptKeyboardAttach](../reference/apis-arkweb/arkts-basic-components-web-events.md#oninterceptkeyboardattach12)被回调。应用可以使用此接口控制软键盘的显示,包括系统默认软键盘、带有特定Enter键的软键盘,或完全自定义软键盘。借助这一功能,开发者能够实现对软键盘的灵活管理。
271
272- 使用系统默认软键盘
273- 使用带有定制Enter键的系统软键盘
274- 使用完全由应用程序自定义的软键盘
275
276```ts
277  // Index.ets
278  import { webview } from '@kit.ArkWeb';
279  import { inputMethodEngine } from '@kit.IMEKit';
280
281  @Entry
282  @Component
283  struct WebComponent {
284    controller: webview.WebviewController = new webview.WebviewController();
285    webKeyboardController: WebKeyboardController = new WebKeyboardController();
286    inputAttributeMap: Map<string, number> = new Map([
287        ['UNSPECIFIED', inputMethodEngine.ENTER_KEY_TYPE_UNSPECIFIED],
288        ['GO', inputMethodEngine.ENTER_KEY_TYPE_GO],
289        ['SEARCH', inputMethodEngine.ENTER_KEY_TYPE_SEARCH],
290        ['SEND', inputMethodEngine.ENTER_KEY_TYPE_SEND],
291        ['NEXT', inputMethodEngine.ENTER_KEY_TYPE_NEXT],
292        ['DONE', inputMethodEngine.ENTER_KEY_TYPE_DONE],
293        ['PREVIOUS', inputMethodEngine.ENTER_KEY_TYPE_PREVIOUS]
294      ])
295
296      /**
297       * 自定义键盘组件Builder
298       */
299      @Builder
300      customKeyboardBuilder() {
301		  // 这里实现自定义键盘组件,对接WebKeyboardController实现输入、删除、关闭等操作。
302        Row() {
303          Text("完成")
304            .fontSize(20)
305            .fontColor(Color.Blue)
306            .onClick(() => {
307              this.webKeyboardController.close();
308            })
309          // 插入字符。
310          Button("insertText").onClick(() => {
311            this.webKeyboardController.insertText('insert ');
312          }).margin({
313            bottom: 200,
314          })
315          // 从后往前删除length参数指定长度的字符。
316          Button("deleteForward").onClick(() => {
317            this.webKeyboardController.deleteForward(1);
318          }).margin({
319            bottom: 200,
320          })
321          // 从前往后删除length参数指定长度的字符。
322          Button("deleteBackward").onClick(() => {
323            this.webKeyboardController.deleteBackward(1);
324          }).margin({
325            left: -220,
326          })
327          // 插入功能按键。
328          Button("sendFunctionKey").onClick(() => {
329            this.webKeyboardController.sendFunctionKey(6);
330          })
331        }
332      }
333
334    build() {
335      Column() {
336        Web({ src: $rawfile('index.html'), controller: this.controller })
337        .onInterceptKeyboardAttach((KeyboardCallbackInfo) => {
338          // option初始化,默认使用系统默认键盘
339          let option: WebKeyboardOptions = {
340            useSystemKeyboard: true,
341          };
342          if (!KeyboardCallbackInfo) {
343            return option;
344          }
345
346          // 保存WebKeyboardController,使用自定义键盘时候,需要使用该handler控制输入、删除、软键盘关闭等行为
347          this.webKeyboardController = KeyboardCallbackInfo.controller;
348          let attributes: Record<string, string> = KeyboardCallbackInfo.attributes;
349          // 遍历attributes
350          let attributeKeys = Object.keys(attributes);
351          for (let i = 0; i < attributeKeys.length; i++) {
352            console.log('WebCustomKeyboard key = ' + attributeKeys[i] + ', value = ' + attributes[attributeKeys[i]]);
353          }
354
355          if (attributes) {
356            if (attributes['data-keyboard'] == 'customKeyboard') {
357              // 根据html可编辑元素的属性,判断使用不同的软键盘,例如这里如果属性包含有data-keyboard,且值为customKeyboard,则使用自定义键盘
358              console.log('WebCustomKeyboard use custom keyboard');
359              option.useSystemKeyboard = false;
360              // 设置自定义键盘builder
361              option.customKeyboard = () => {
362                this.customKeyboardBuilder()
363              }
364              return option;
365            }
366
367            if (attributes['keyboard-return'] != undefined) {
368              // 根据html可编辑元素的属性,判断使用不同的软键盘,例如这里如果属性包含有keyboard-return,使用系统键盘,并且指定系统软键盘enterKey类型
369              option.useSystemKeyboard = true;
370              let enterKeyType: number | undefined = this.inputAttributeMap.get(attributes['keyboard-return']);
371              if (enterKeyType != undefined) {
372                option.enterKeyType = enterKeyType;
373              }
374              return option;
375            }
376          }
377
378          return option;
379        })
380      }
381    }
382  }
383```
384
385```html
386<!-- index.html -->
387    <!DOCTYPE html>
388    <html>
389
390    <head>
391        <meta charset="utf-8">
392        <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0">
393    </head>
394
395    <body>
396
397    <p style="font-size:12px">input标签,原有默认行为:</p>
398    <input type="text" style="width: 300px; height: 20px"><br>
399    <hr style="height:2px;border-width:0;color:gray;background-color:gray">
400
401    <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key UNSPECIFIED:</p>
402    <input type="text" keyboard-return="UNSPECIFIED" style="width: 300px; height: 20px"><br>
403    <hr style="height:2px;border-width:0;color:gray;background-color:gray">
404
405    <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key GO:</p>
406    <input type="text" keyboard-return="GO" style="width: 300px; height: 20px"><br>
407    <hr style="height:2px;border-width:0;color:gray;background-color:gray">
408
409    <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key SEARCH:</p>
410    <input type="text" keyboard-return="SEARCH" style="width: 300px; height: 20px"><br>
411    <hr style="height:2px;border-width:0;color:gray;background-color:gray">
412
413    <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key SEND:</p>
414    <input type="text" keyboard-return="SEND" style="width: 300px; height: 20px"><br>
415    <hr style="height:2px;border-width:0;color:gray;background-color:gray">
416
417    <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key NEXT:</p>
418    <input type="text" keyboard-return="NEXT" style="width: 300px; height: 20px"><br>
419    <hr style="height:2px;border-width:0;color:gray;background-color:gray">
420
421    <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key DONE:</p>
422    <input type="text" keyboard-return="DONE" style="width: 300px; height: 20px"><br>
423    <hr style="height:2px;border-width:0;color:gray;background-color:gray">
424
425    <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key PREVIOUS:</p>
426    <input type="text" keyboard-return="PREVIOUS" style="width: 300px; height: 20px"><br>
427    <hr style="height:2px;border-width:0;color:gray;background-color:gray">
428
429    <p style="font-size:12px">input标签,应用自定义键盘:</p>
430    <input type="text" data-keyboard="customKeyboard" style="width: 300px; height: 20px"><br>
431
432    </body>
433
434    </html>
435```
436
437ArkWeb自定义键盘的示例效果如图4、图5和图6所示。
438
439**图4**  ArkWeb自定义键盘数字键盘
440
441![web-customkeyboardnumber](figures/web-customkeyboardnumber.png)
442
443**图5**  ArkWeb自定义键盘字母键盘
444
445![web-customkeyboardletter](figures/web-customkeyboardletter.png)
446
447**图6**  ArkWeb自定义键盘符号键盘
448
449![web-customkeyboardsymbol](figures/web-customkeyboardsymbol.png)