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;…

1分钟了解LangChain4j是什么?

一: LangChain4j介绍 LangChain现在仅支持​ Python语言与Javascript语言&#xff0c; 而LangChain4J就是属于Java版本的 LangChain&#xff0c;它的目的也是简化LLM&#xff08;大语言模型&#xff09;与Java应用程序的集成。 大模型时代&#xff0c;如何将大模型能力和传统应…

如何使用Xcode查看iOS APP客户端日志

在测试iOS app过程中&#xff0c;能够有效查看和分析客户端日志是至关重要的。不论是定位crash还是解决复杂的逻辑错误&#xff0c;日志都扮演了不可或缺的角色。Apple的Xcode提供了一个强大的工具集&#xff0c;帮助测试同学有效地进行日志查看和分析。本文将逐步指导如何使用…

深入剖析:Postman报错排查全攻略

&#x1f50d; 深入剖析&#xff1a;Postman报错排查全攻略 Postman作为API开发和测试的强大工具&#xff0c;虽然功能强大&#xff0c;但在使用过程中难免会遇到各种报错问题。本文将带领你深入排查Postman中的常见错误&#xff0c;提供全面的解决方案&#xff0c;让你能够快…

ubuntu语音库ALSA报错具体原因

在ubuntu中使用pyaudio或portaudio时总会有下面的提示&#xff0c;不胜其烦。 ALSA lib pcm_dsnoop.c:612:(snd_pcm_dsnoop_open) unable to open slave ALSA lib pcm_dmix.c:1018:(snd_pcm_dmix_open) unable to open slave ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unkn…

PyTorch学习之torch.matmul函数

PyTorch学习之torch.matmul函数 一、简介 torch.matmul 用于两维或更高维张量的矩阵乘法操作。它支持广播机制&#xff0c;并且能够处理不同形状和维度的张量&#xff0c;适用于广泛的应用场景。 二、语法 torch.matmul 函数的基本语法如下&#xff1a; torch.matmul(inpu…

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

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

C++纯虚函数的理解,纯虚函数和派生类的关系。

在 C 中&#xff0c;纯虚函数&#xff08;pure virtual function&#xff09;是一种特殊的虚函数&#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框架就可以了