HarmonyOS开发探索:自定义键盘-webview

场景描述

在特殊的H5场景下需要应用拉起自定义键盘进行输入。

场景一:使用jsBridge拉起自定义弹窗写自定义键盘,再通过jsBridge传参实现输入。

场景二:使用web的同层渲染将原生textInput组件渲染到页面上。

方案描述

通过注册一个js代理对象被web的registerJavaScriptProxy方法调用拉起CustomDialog,在CustomDialog上放置一个customkeyboard

场景一:通过jsBridge拉起自定义弹窗,在自定义弹窗上放置自定义键盘,例如需要输入密码时的安全键盘

效果图

cke_23701.gif

方案

通过注册一个js代理对象被web的registJavaScriptProxy方法调用拉起CustomDialog,在CustomDialog上放置一个自定义键盘组件,通过在H5上input标签的readonly属性和注册的js方法changeNumbers实现在原生端输入数字传到H5上,他们之间通过@Link装饰器绑定的变量进行传值,所以点击删除输入的内容也是可以在H5上实现的。

核心代码

  1. 通过javaScriptProxy方法拉起自定义弹窗,在H5上的input标签绑定一个onclick事件,当点击输入框后会调用从原生注册过来的js代理方法openWindow。

    <input type="text" name="number_info" readonly onclick="openWindow()" value="" style="width: 500px;height: 100px;font-size:50px;border:1px solid # f00;"><script>function openWindow() {let value = document.getElementsByName("number_info")[0].value;window.myJsb.openDialog(value)}</script>

  2. 当H5上openWindow方法被调用后会通过jsBridge调用以下两个js代理方法打开自定义弹窗。

    jsbObject: JsbObject = {openDialog: (value: string) => {this.showDialog(this, value);}}showDialog(context: object, value: string) {// 把自定义弹窗调出来this.currentData = value;this.dialogController.open()}Web({ src: "resource://rawfile/web_test.html", controller: this.webviewController }).javaScriptAccess(true).javaScriptProxy({name: "myJsb",object: this.jsbObject,methodList: ["openDialog"],controller: this.webviewController})
  3. 将自定义键盘放置在自定义弹窗上。

    @CustomDialogstruct CustomDialogExample {@Link currentData: stringdialogControllerTwo: CustomDialogController | null = new CustomDialogController({builder: CustomDialogExample({ currentData: $currentData }),alignment: DialogAlignment.Bottom,offset: { dx: 0, dy: -25 }})controller?: CustomDialogControllerbuild() {Column() {Button('x').onClick(() => {// 关闭自定义键盘if (this.controller != undefined) {this.controller.close()}})Grid() {ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, '*', 0, '删除'], (item: number | string) => {GridItem() {Button(item + "").width(110).onClick(() => {if (item == '删除') {if (this.currentData.length > 0) {this.currentData = this.currentData.substring(0, this.currentData.length - 1);}} else {this.currentData += item}})}})}.maxCount(3).columnsGap(10).rowsGap(10).padding(5)}.backgroundColor(Color.Gray)}}
  4. 在自定义键盘上输入内容的时候会调用onChangeInputValue方法,通过里面的runJavaScript调用H5上的js方法changeNumber传值到H5的输入框中。

    onChangeInputValue(stateName: string){console.log('this.currentData:' + this.currentData)this.webviewController.runJavaScript('changeNumber("'+ this.currentData +'")').then((result) => {console.log('result: ' + result);})}<<input type="text" name="number_info" readonly onclick="openWindow()" value="" style="width: 500px;height: 100px;font-size:50px;border:1px solid # f00;" /><script>function changeNumber(value){document.getElementsByName("number_info")[0].value = value;}</script>

场景二:通过同层渲染渲染一个原生的自定义键盘

效果图

cke_28481.gif

方案

整体实现效果为:通过web的同层渲染功能实现将原生TextInput组件渲染到H5需要使用自定义键盘的页面中,这样就可以实现在H5拉起自定义键盘,并且使用它的全部功能。

核心代码

  1. 创建一个自定义键盘并绑定到原生textInput组件上。

    @Componentstruct ButtonComponent {controller1: TextInputController = new TextInputController()@State inputValue: string = ""// 自定义键盘组件@BuilderCustomKeyboardBuilder() {Column() {Button('x').onClick(() => {// 关闭自定义键盘this.controller1.stopEditing()})Grid() {ForEach([1, 2, 3, 4, 5, 6, 7, 8, 9, '*', 0, '# '], (item: number | string) => {GridItem() {Button(item + "").width(110).onClick(() => {this.inputValue += item})}})}.maxCount(3).columnsGap(10).rowsGap(10).padding(5)}.backgroundColor(Color.Pink)}@ObjectLink params: Params@State bkColor: Color = Color.Red@State outSetValueTwo: number = 40@State outSetValueOne: number = 40@State tipsValue: number = 40controller: web_webview.WebviewController = new web_webview.WebviewController();build() {Column() {TextInput({ controller: this.controller1, text: this.inputValue })// 绑定自定义键盘.customKeyboard(this.CustomKeyboardBuilder()).margin(10).border({ width: 1 })}.width(this.params.width).height(this.params.height)}}
  2. 将原生textInput组件通过web同层渲染功能渲染到H5上的embed标签上。

    @Entry@Componentstruct WebIndex {browserTabController: WebviewController = new webview.WebviewController()build() {Column() {Web({ src: $rawfile("test.html"), controller: this.browserTabController })// 配置同层渲染开关开启。.enableNativeEmbedMode(true)// 获取embed标签的生命周期变化数据。.onNativeEmbedLifecycleChange((embed) => {console.log("NativeEmbed surfaceId" + embed.surfaceId);// 获取web侧embed元素的id。const componentId = embed.info?.id?.toString() as stringif (embed.status == NativeEmbedStatus.CREATE) {console.log("NativeEmbed create" + JSON.stringify(embed.info))// 创建节点控制器,设置参数并rebuild。let nodeController = new MyNodeController()nodeController.setRenderOption({surfaceId: embed.surfaceId as string,type: embed.info?.type as string,renderType: NodeRenderType.RENDER_TYPE_TEXTURE,embedId: embed.embedId as string,width: px2vp(embed.info?.width),height: px2vp(embed.info?.height)})nodeController.setDestroy(false);// 根据web传入的embed的id属性作为key,将nodeController存入map。this.nodeControllerMap.set(componentId, nodeController)// 将web传入的embed的id属性存入@State状态数组变量中,用于动态创建nodeContainer节点容器,需要将push动作放在set之后。this.componentIdArr.push(componentId)} else if (embed.status == NativeEmbedStatus.UPDATE) {let nodeController = this.nodeControllerMap.get(componentId)nodeController?.updateNode({textOne: 'update',width: px2vp(embed.info?.width),height: px2vp(embed.info?.height)} as ESObject)} else {let nodeController = this.nodeControllerMap.get(componentId);nodeController?.setDestroy(true)this.nodeControllerMap.clear();this.componentIdArr.length = 0;}})// 获取同层渲染组件触摸事件信息。.onNativeEmbedGestureEvent((touch) => {console.log("NativeEmbed onNativeEmbedGestureEvent" + JSON.stringify(touch.touchEvent));this.componentIdArr.forEach((componentId: string) => {let nodeController = this.nodeControllerMap.get(componentId)if (nodeController?.getEmbedId() === touch.embedId) {let ret = nodeController?.postEvent(touch.touchEvent)if (ret) {console.log("onNativeEmbedGestureEvent success " + componentId)} else {console.log("onNativeEmbedGestureEvent fail " + componentId)}}})})}}}<html><head><title>同层渲染测试html</title><meta name="viewport"></head><body><div><div id="bodyId"><embed id="nativeTextInput" type="native/TextInput" width="100%" height="100%" src="test?params1=xxx?"style="background-color:pink"/></div></div></body></html>


最后

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?但是又不知道从哪里下手,而且学习时频繁踩坑,最终浪费大量时间。所以本人整理了一些比较合适的鸿蒙(HarmonyOS NEXT)学习路径和一些资料的整理供小伙伴学习

点击领取→纯血鸿蒙Next全套最新学习资料(安全链接,放心点击

希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!

一、鸿蒙(HarmonyOS NEXT)最新学习路线

有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)…等技术知识点。

获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料

二、HarmonyOS Next 最新全套视频教程

三、《鸿蒙 (OpenHarmony)开发基础到实战手册》

OpenHarmony北向、南向开发环境搭建

《鸿蒙开发基础》

  • ArkTS语言
  • 安装DevEco Studio
  • 运用你的第一个ArkTS应用
  • ArkUI声明式UI开发
  • .……

《鸿蒙开发进阶》

  • Stage模型入门
  • 网络管理
  • 数据管理
  • 电话服务
  • 分布式应用开发
  • 通知与窗口管理
  • 多媒体技术
  • 安全技能
  • 任务管理
  • WebGL
  • 国际化开发
  • 应用测试
  • DFX面向未来设计
  • 鸿蒙系统移植和裁剪定制
  • ……

《鸿蒙进阶实战》

  • ArkTS实践
  • UIAbility应用
  • 网络案例
  • ……

四、大厂面试必问面试题

五、鸿蒙南向开发技术

六、鸿蒙APP开发必备

七、鸿蒙生态应用开发白皮书V2.0PDF


完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料

总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。 

                        

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/38603.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue-element 组件dialog右上角点击 X 清空表单校验信息

问题&#xff1a; 点击确定触发校验后&#xff0c;点击弹窗右上角的 X号关闭弹窗后再次打开弹窗&#xff0c;校验规则没有被清空 解决方法&#xff1a;

Asp.NET identity以及Owin

》》》Identity是集成到Owin框架中中 ● Microsoft.AspNet.Identity.Core&#xff1a;Identity的核心类库&#xff0c;实现了身份验证的核心功能&#xff0c;并提供了拓展接口。● Microsoft.AspNet.Identity.EntityFramework&#xff1a;Identity数据持久化的EF实现。   ● …

Soul探索未来智能互动模式,人机交互重塑社交元宇宙体验

在当今快速发展的科技领域中,人机交互已成为一个备受关注的话题。随着人工智能和机器学习技术的不断进步,人们与计算机和智能设备之间的互动方式正在发生翻天覆地的变化。这种交互不止局限于键盘和鼠标,更涵盖了语音识别、手势控制、虚拟现实等多种形式。人机交互的创新不仅提高…

七一建党节|热烈庆祝中国共产党成立103周年!

时光荏苒&#xff0c;岁月如梭。 在这热情似火的夏日&#xff0c; 我们迎来了中国共产党成立103周年的重要时刻。 这是一个值得全体中华儿女共同铭记和庆祝的日子&#xff0c; 也是激励我们不断前进的重要时刻。 103年&#xff0c; 风雨兼程&#xff0c;砥砺前行。 从嘉兴…

CesiumJS【Basic】- #038 绘制轮廓线(Primitive方式)

文章目录 绘制轮廓线(Primitive方式)1 目标2 代码2.1 main.ts绘制轮廓线(Primitive方式) 1 目标 使用Primitive方式绘制轮廓线 2 代码 2.1 main.ts var start = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);v

DX-11A信号继电器 0.5A 柜内板前接线 约瑟JOSEF

DX-11,11A,11B,11C型信号继电器 DX-11信号继电器 DX-11B信号继电器 DX-11A信号继电器 DX-11C信号继电器 1 用途 该继电器用于直流操作的保护线路中&#xff0c;作为信号指示器。 2 结构和原理 该继电器具有电磁铁和带公共点的三付动合触点及一个信号牌&#xff0c;为电…

嵌入式Linux系统编程 — 5.6 Linux系统申请堆内存

目录 1 内存概念 1.1 什么是堆内存 1.2 内存分布 2 malloc、free在堆上分配与释放内存 2.1 malloc函数 2.2 free函数 2.3 示例程序 注意事项&#xff1a; 3 calloc分配内存 3.1 calloc函数介绍 3.2 示例程序 4 分配对齐内存 4.1 函数介绍 4.2 示例程序 1 内存概念…

推荐下载:Windows11 23H2专业工作站版!高效办公首选!

今天系统之家小编给需要高性能计算能力、高级安全功能和专业级应用程序支持的用户推荐一款操作系统&#xff0c;那就是Windows11 23H2专业工作站版系统&#xff0c;该系统经过优化&#xff0c;具有更强的数据处理能力和更高的安全性&#xff0c;还具有出色的兼容性&#xff0c;…

论文笔记:MobilityGPT: Enhanced Human MobilityModeling with a GPT mode

1 intro 1.1 背景 尽管对人类移动轨迹数据集的需求不断增加&#xff0c;但其访问和分发仍面临诸多挑战 首先&#xff0c;这些数据集通常由私人公司或政府机构收集&#xff0c;因此可能因泄露个人敏感生活模式而引发隐私问题其次&#xff0c;公司拥有的数据集可能会暴露专有商…

PAI3D: Painting Adaptive Instance-Prior for 3D Object Detection论文讲解

PAI3D: Painting Adaptive Instance-Prior for 3D Object Detection论文讲解 1. 引言2. PAI3D框架2.1 Instance Painter2.2 Adaptive Projection Refiner2.3 Fine-granular Detection Head 3. 实验结果3.1 消融实验 1. 引言 3D目标检测对于自动驾驶来说是一个非常重要的模块&a…

如何现代的编译和安装内核

前言&#xff1a;本文是在阅读书目时找到了一篇非常高质量的文章。的原文是英文&#xff0c;现在我自己手头翻译了一下&#xff0c;发布到这里。 原文连接&#xff1a;How to compile a Linux kernel in the 21st century | Opensource.com 目录 更新内核的现代方法 安装内…

C++知识点总结全系列 (05):IO 类的详细总结和分析

1、基类 istream 和 ostream (1)istream A.What 输入流的抽象类&#xff0c;是所有输入流类的基类 B.Why&#xff08;输入流的作用&#xff09; 用于从数据源&#xff08;如文件、标准输入设备等&#xff09;读取数据 (2)ostream A.What 输出流的抽象类&#xff0c;是所有输…

grpc学习golang版( 六、服务器流式传输 )

系列文章目录 第一章 grpc基本概念与安装 第二章 grpc入门示例 第三章 proto文件数据类型 第四章 多服务示例 第五章 多proto文件示例 第六章 服务器流式传输 第七章 客户端流式传输 第八章 双向流示例 文章目录 一、前言二、定义proto文件三、拷贝任意文件进项目四、编写serve…

复制完若依后,idea没有maven窗口

右击项目 添加框架 添加maven框架就可以了

大数据开发中的数据倾斜问题

数据倾斜是大数据开发中常见的性能瓶颈&#xff0c;了解其原因并采取有效的解决方案对系统性能至关重要。本文将从数据倾斜的影响、解决方法及示例代码等方面进行详细讨论。 目录 1. 数据倾斜的影响2. 解决数据倾斜的方法调整分区键预聚合倾斜处理逻辑 3. 进一步解决数据倾斜的…

vue3.0 + vant实现下拉刷新上拉加载

在vue中使用vant组件库有个van-pull-refresh下拉组件&#xff0c;配合van-list列表组件实现页面的下拉刷新和上拉加载&#xff0c;原理简单&#xff0c;适用场景在列表页面内容展示。 下拉刷新 PullRefresh 实现下拉刷新的效果。 PullRefresh组件中的searchRefreshing属性&…

51单片机嵌入式开发:STC89C52环境配置到点亮LED

STC89C52环境配置到点亮LED 1 环境配置1.1 硬件环境1.2 编译环境1.3 烧录环境 2 工程配置2.1 工程框架2.2 工程创建2.3 参数配置 3 点亮一个LED3.1 原理图解读3.2 代码配置3.3 演示 4 总结 1 环境配置 1.1 硬件环境 硬件环境采用“华晴电子”的MINIEL-89C开发板&#xff0c;这…

安卓app开发-基础-本地环境安装android studio且配置参数

安卓app开发-基础-本地环境安装android studio且配置参数&#xff01;今天为大家介绍一下&#xff0c;如何在自己本地电脑安装android ,studio和启动一个简单的java版本的项目。 第一步&#xff0c;去下面的地址&#xff0c;下载一个安装文件。 地址&#xff1a;AndroidDevToo…

root密码忘了怎么办(从系统引导过程解决)

目录 1.Linux系统密码忘记 2.系统引导过程 2.1 systemd 2.2 GRUB和GRUB2 2.3 运行级别 3.修复MBR扇区故障和GRUB引导故障 3.1 MBR扇区故障 3.2 GRUB引导故障 1.Linux系统密码忘记 我们在生活中经常遇到这类困扰&#xff0c;就是某个账号还是账户密码忘了&#xff0c;这…

Docker的理解

Docker的理解 Docker为什么用Docker&#xff1f;1.提升系统资源利用率2.更快速的交付和部署3.高效的部署和扩容4.更简单的管理 Docker核心技术Docker镜像Docker容器Docker仓库 Docker实现原理Linux NamespaceCgroupUnion FS Docker的应用场景1.微服务架构2.持续集成3.快速部署和…