【鸿蒙实战开发】基于webview拉起自定义键盘

100 篇文章 1 订阅
100 篇文章 2 订阅

场景描述

在特殊的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>

鸿蒙全栈开发全新学习指南

有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以要有一份实用的鸿蒙(HarmonyOS NEXT)学习路线与学习文档用来跟着学习是非常有必要的。

针对一些列因素,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线,包含了鸿蒙开发必掌握的核心知识要点,内容有(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、WebGL、元服务、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、OpenHarmony驱动开发、系统定制移植等等)鸿蒙(HarmonyOS NEXT)技术知识点。

本路线共分为四个阶段

第一阶段:鸿蒙初中级开发必备技能

在这里插入图片描述

第二阶段:鸿蒙南北双向高工技能基础:gitee.com/MNxiaona/733GH

在这里插入图片描述

第三阶段:应用开发中高级就业技术

第四阶段:全网首发-工业级南向设备开发就业技术:gitee.com/MNxiaona/733GH

在这里插入图片描述

《鸿蒙 (Harmony OS)开发学习手册》(共计892页)

如何快速入门?

1.基本概念
2.构建第一个ArkTS应用
3.……

开发基础知识:gitee.com/MNxiaona/733GH

1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……

在这里插入图片描述

基于ArkTS 开发

1.Ability开发
2.UI开发
3.公共事件与通知
4.窗口管理
5.媒体
6.安全
7.网络与链接
8.电话服务
9.数据管理
10.后台任务(Background Task)管理
11.设备管理
12.设备使用信息统计
13.DFX
14.国际化开发
15.折叠屏系列
16.……

在这里插入图片描述

鸿蒙开发面试真题(含参考答案):gitee.com/MNxiaona/733GH

在这里插入图片描述

鸿蒙入门教学视频:

美团APP实战开发教学:gitee.com/MNxiaona/733GH

写在最后

  • 如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:
  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力。
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识。
  • 想要获取更多完整鸿蒙最新学习资源,请移步前往小编:gitee.com/MNxiaona/733GH

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值