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属性用于配置输入法类型。 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<!DOCTYPE html> 110<html> 111 <head> 112 <title>测试网页</title> 113 </head> 114 <body> 115 <h1>DEMO</h1> 116 <input type="text" id="input_a"> 117 </body> 118</html> 119``` 120 121```ts 122//Index.ets 123@Entry 124@Component 125struct KeyboardAvoidExample { 126 controller: web_webview.WebviewController = new web_webview.WebviewController(); 127 build() { 128 Column() { 129 Row().height("50%").width("100%").backgroundColor(Color.Gray) 130 Web({ src: $rawfile("index.html"),controller: this.controller}) 131 Text("I can see the bottom of the page").width("100%").textAlign(TextAlign.Center).backgroundColor(Color.Pink).layoutWeight(1) 132 }.width('100%').height("100%") 133 } 134} 135``` 136此时ArkWeb组件跟随ArkUI重新布局,效果如图1、图2所示。 137 138**图1** Web组件网页默认软键盘避让模式 139 140 141 142**图2** Web组件网页跟随Arkui软键盘避让模式 143 144 145 1462.在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。 147 148- RESIZE_VISUAL:仅调整可视视口的大小,而不调整布局视口的大小。 149- RESIZE_CONTENT:调整视觉视口和布局视口的大小。 150- OVERLAYS_CONTENT:不调整任何视口的大小,获焦input元素没有滚动到可识区域的行为。 151 152>**说明:** 153> 154>可视视口指用户正在看到的网站的区域,该区域的宽度等于移动设备的浏览器窗口的宽度。 155> 156>布局视口指网页本身的宽度。 157 158(1)在应用代码中设置ArkWeb的软键盘避让模式。 159 160```ts 161// Index.ets 162@Entry 163@Component 164struct KeyboardAvoidExample { 165 controller: web_webview.WebviewController = new web_webview.WebviewController(); 166 build() { 167 Column() { 168 Row().height("50%").width("100%").backgroundColor(Color.Gray) 169 Web({ src: $rawfile("index.html"),controller: this.controller}) 170 .keyboardAvoidMode(WebKeyboardAvoidMode.OVERLAYS_CONTENT) //此时ArkWeb组件不会调整任何视口的大小大小 171 Text("I can see the bottom of the page").width("100%").textAlign(TextAlign.Center).backgroundColor(Color.Pink).layoutWeight(1) 172 }.width('100%').height("100%") 173 } 174} 175``` 176此时ArkWeb组件根据自身的避让模式进行避让,效果如图3所示。 177 178**图3** Web组件网页自身软键盘避让模式 179 180 181 182与其他Web组件行为的交叉场景: 183 184| 交叉场景 | 规格 | 185| ------------ | ---------------------------------------- | 186| 同层渲染 | 同层Web:软键盘避让行为与普通场景行为一致 同层原生组件:由ArkUI负责软键盘避让模式。 | 187| 离屏创建组件 | 默认使用与非离屏创建一致的软键盘避让模式 在上树前设置其他避让模式可需生效。 | 188| customDialog | customDialog自身避让。 | 189| 折叠屏 | 软键盘避让行为与普通场景行为一致 软件键盘需跟随屏幕开合状态进展开合变化。 | 190| 软键盘托管 | 软键盘避让行为与普通场景行为一致。 | 191| Web嵌套滚动 | 嵌套滚动场景下不推荐使用Web软键盘避让,包括RESIZE_VISUAL与RESIZE_CONTENT。 | 192 193 194 195## 拦截系统软键盘与自定义软键盘输入 196 197应用能够通过调用[onInterceptKeyboardAttach](../reference/apis-arkweb/ts-basic-components-web.md#oninterceptkeyboardattach12)来拦截系统软键盘的弹出。在网页中,当可编辑元素如input标签即将触发软键盘显示时,[onInterceptKeyboardAttach](../reference/apis-arkweb/ts-basic-components-web.md#oninterceptkeyboardattach12)会被回调。应用可利用此接口来控制软键盘的显示,包括使用系统默认软键盘、定制带有特定Enter键的软键盘,或是完全自定义软键盘。借助这一功能,开发者能够实现对软键盘的灵活管理。 198 199- 使用系统默认软键盘 200- 使用定制Enter键的系统软键盘 201- 使用完全由应用自定义的软键盘 202 203```ts 204 // xxx.ets 205 import { webview } from '@kit.ArkWeb'; 206 import { inputMethodEngine } from '@kit.IMEKit'; 207 208 @Entry 209 @Component 210 struct WebComponent { 211 controller: webview.WebviewController = new webview.WebviewController(); 212 webKeyboardController: WebKeyboardController = new WebKeyboardController() 213 inputAttributeMap: Map<string, number> = new Map([ 214 ['UNSPECIFIED', inputMethodEngine.ENTER_KEY_TYPE_UNSPECIFIED], 215 ['GO', inputMethodEngine.ENTER_KEY_TYPE_GO], 216 ['SEARCH', inputMethodEngine.ENTER_KEY_TYPE_SEARCH], 217 ['SEND', inputMethodEngine.ENTER_KEY_TYPE_SEND], 218 ['NEXT', inputMethodEngine.ENTER_KEY_TYPE_NEXT], 219 ['DONE', inputMethodEngine.ENTER_KEY_TYPE_DONE], 220 ['PREVIOUS', inputMethodEngine.ENTER_KEY_TYPE_PREVIOUS] 221 ]) 222 223 /** 224 * 自定义键盘组件Builder 225 */ 226 @Builder 227 customKeyboardBuilder() { 228 // 这里实现自定义键盘组件,对接WebKeyboardController实现输入、删除、关闭等操作。 229 Row() { 230 Text("完成") 231 .fontSize(20) 232 .fontColor(Color.Blue) 233 .onClick(() => { 234 this.webKeyboardController.close(); 235 }) 236 // 插入字符。 237 Button("insertText").onClick(() => { 238 this.webKeyboardController.insertText('insert '); 239 }).margin({ 240 bottom: 200, 241 }) 242 // 从后往前删除length参数指定长度的字符。 243 Button("deleteForward").onClick(() => { 244 this.webKeyboardController.deleteForward(1); 245 }).margin({ 246 bottom: 200, 247 }) 248 // 从前往后删除length参数指定长度的字符。 249 Button("deleteBackward").onClick(() => { 250 this.webKeyboardController.deleteBackward(1); 251 }).margin({ 252 left: -220, 253 }) 254 // 插入功能按键。 255 Button("sendFunctionKey").onClick(() => { 256 this.webKeyboardController.sendFunctionKey(6); 257 }) 258 } 259 } 260 261 build() { 262 Column() { 263 Web({ src: $rawfile('index.html'), controller: this.controller }) 264 .onInterceptKeyboardAttach((KeyboardCallbackInfo) => { 265 // option初始化,默认使用系统默认键盘 266 let option: WebKeyboardOptions = { 267 useSystemKeyboard: true, 268 }; 269 if (!KeyboardCallbackInfo) { 270 return option; 271 } 272 273 // 保存WebKeyboardController,使用自定义键盘时候,需要使用该handler控制输入、删除、软键盘关闭等行为 274 this.webKeyboardController = KeyboardCallbackInfo.controller 275 let attributes: Record<string, string> = KeyboardCallbackInfo.attributes 276 // 遍历attributes 277 let attributeKeys = Object.keys(attributes) 278 for (let i = 0; i < attributeKeys.length; i++) { 279 console.log('WebCustomKeyboard key = ' + attributeKeys[i] + ', value = ' + attributes[attributeKeys[i]]) 280 } 281 282 if (attributes) { 283 if (attributes['data-keyboard'] == 'customKeyboard') { 284 // 根据html可编辑元素的属性,判断使用不同的软键盘,例如这里如果属性包含有data-keyboard,且值为customKeyboard,则使用自定义键盘 285 console.log('WebCustomKeyboard use custom keyboard') 286 option.useSystemKeyboard = false; 287 // 设置自定义键盘builder 288 option.customKeyboard = () => { 289 this.customKeyboardBuilder() 290 } 291 return option; 292 } 293 294 if (attributes['keyboard-return'] != undefined) { 295 // 根据html可编辑元素的属性,判断使用不同的软键盘,例如这里如果属性包含有keyboard-return,使用系统键盘,并且指定系统软键盘enterKey类型 296 option.useSystemKeyboard = true; 297 let enterKeyType: number | undefined = this.inputAttributeMap.get(attributes['keyboard-return']) 298 if (enterKeyType != undefined) { 299 option.enterKeyType = enterKeyType 300 } 301 return option; 302 } 303 } 304 305 return option; 306 }) 307 } 308 } 309 } 310``` 311 312```html 313<!-- index.html --> 314 <!DOCTYPE html> 315 <html> 316 317 <head> 318 <meta charset="utf-8"> 319 <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0"> 320 </head> 321 322 <body> 323 324 <p style="font-size:12px">input标签,原有默认行为:</p> 325 <input type="text" style="width: 300px; height: 20px"><br> 326 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 327 328 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key UNSPECIFIED:</p> 329 <input type="text" keyboard-return="UNSPECIFIED" style="width: 300px; height: 20px"><br> 330 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 331 332 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key GO:</p> 333 <input type="text" keyboard-return="GO" style="width: 300px; height: 20px"><br> 334 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 335 336 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key SEARCH:</p> 337 <input type="text" keyboard-return="SEARCH" style="width: 300px; height: 20px"><br> 338 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 339 340 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key SEND:</p> 341 <input type="text" keyboard-return="SEND" style="width: 300px; height: 20px"><br> 342 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 343 344 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key NEXT:</p> 345 <input type="text" keyboard-return="NEXT" style="width: 300px; height: 20px"><br> 346 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 347 348 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key DONE:</p> 349 <input type="text" keyboard-return="DONE" style="width: 300px; height: 20px"><br> 350 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 351 352 <p style="font-size:12px">input标签,系统键盘自定义enterKeyType属性 enter key PREVIOUS:</p> 353 <input type="text" keyboard-return="PREVIOUS" style="width: 300px; height: 20px"><br> 354 <hr style="height:2px;border-width:0;color:gray;background-color:gray"> 355 356 <p style="font-size:12px">input标签,应用自定义键盘:</p> 357 <input type="text" data-keyboard="customKeyboard" style="width: 300px; height: 20px"><br> 358 359 </body> 360 361 </html> 362``` 363 364ArkWeb自定义键盘示例效果如图4、图5、图6所示。 365 366**图4** ArkWeb自定义键盘数字键盘 367 368 369 370**图5** ArkWeb自定义键盘字母键盘 371 372 373 374**图6** ArkWeb自定义键盘符号键盘 375 376