当前位置: 首页 > news >正文

鸿蒙5.0实战案例:基于webview拉起自定义键盘

往期推文全新看点(文中附带全新鸿蒙5.0全栈学习笔录)

✏️ 鸿蒙(HarmonyOS)北向开发知识点记录~

✏️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~

✏️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?

✏️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~

✏️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?

✏️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?

✏️ 记录一场鸿蒙开发岗位面试经历~

✏️ 持续更新中……


场景描述

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

  • 场景一:使用jsBridge拉起自定义弹窗写自定义键盘,再通过jsBridge传参实现输入。
  • 场景二:使用web的同层渲染将原生textInput组件渲染到页面上。

方案描述

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

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

效果图

方案

通过注册一个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>
  1. 当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

    })
  1. 将自定义键盘放置在自定义弹窗上。
    @CustomDialog

    struct CustomDialogExample {

    @Link currentData: string

    dialogControllerTwo: CustomDialogController | null = new CustomDialogController({

    builder: CustomDialogExample({ currentData: $currentData }),

    alignment: DialogAlignment.Bottom,

    offset: { dx: 0, dy: -25 }

    })

    controller?: CustomDialogController

    build() {

    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)

    }

    }
  1. 在自定义键盘上输入内容的时候会调用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>

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

效果图

方案

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

核心代码

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

    struct ButtonComponent {

    controller1: TextInputController = new TextInputController()

    @State inputValue: string = ""

    // 自定义键盘组件

    @Builder

    CustomKeyboardBuilder() {

    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 = 40

    controller: 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)

    }

    }
  1. 将原生textInput组件通过web同层渲染功能渲染到H5上的embed标签上。
    @Entry

    @Component

    struct 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 string

    if (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>

相关文章:

  • VS2015 c++和cmake配置编程
  • Github 2025-03-03 开源项目周报Top14
  • QTableWidget之表格列的隐藏与显示(折叠)
  • C++并发以及多线程的秘密
  • C#—csv文件格式操作
  • stm32移植LCD2002驱动
  • 爬虫逆向实战小记——解决webpack实记
  • 歌叽歌叽V2.0.5--原创音乐制作工具安装与部署
  • linux 如何查看gpu使用情况
  • 深入解析Tiktokenizer:大语言模型中核心分词技术的原理与架构
  • Java分支和循环结构详解/while/do while /for循环详解/死循环/Random用法
  • 如何优化Android应用的性能
  • leetcode113-路径总和II
  • STM32---FreeRTOS中断管理试验
  • WebP2P技术在嵌入式设备中的应用:EasyRTC音视频通话SDK如何实现高效通信?
  • Baklib内容中台赋能企业智管
  • FastGPT 源码:如何实现 “问题优化“
  • 【Canny 边缘检测详细讲解】
  • 深度学习-大白话解释循环神经网络RNN
  • C高级linux
  • 服务器搭建网站空间/长沙网站推广公司
  • 做养生网站需要证件吗/seo竞价推广
  • 深圳市招聘信息网站/码迷seo
  • 做的网站浏览器提示不安全问题/网站建设平台有哪些
  • 简单设计网站/广州网站到首页排名
  • 微信如何做自己的网站/优化设计五年级下册语文答案