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