赞
踩
金融类应用在密码输入时,一般会使用自定义安全键盘。本示例介绍如何使用TextInput组件实现自定义安全键盘场景,主要包括TextInput.customKeyboard绑定自定义键盘、自定义键盘布局和状态更新等知识点。
当设置自定义键盘时,输入框激活后不会打开系统输入法,而是加载应用指定的自定义组件,针对系统键盘的enterKeyType属性设置将无效。自定义键盘采用覆盖原始界面的方式呈现,不会对应用原始界面产生压缩或者上提。默认在输入控件失去焦点时,关闭自定义键盘,开发者也可以通过TextInputController.stopEditing方法控制键盘关闭。
键盘枚举类型:
/** * 键盘类型枚举 */ export enum EKeyboardType { NUMERIC, //数字键盘 UPPERCASE, // 大写字母键盘 LOWERCASE, // 小写字母键盘 SPECIAL, // 特殊字符键盘 } /** * 键盘按键类型枚举 */ export enum EKeyType { INPUT, // 输入类型,输入具体的值 DELETE, // 删除一个输入字符 NUMERIC, // 切换数字键盘 CAPSLOCK, // 切换大小写键盘 SPECIAL, // 切换特殊字符键盘 }
在真实业务场景下,自定义安全键盘数据包括值、UI属性、位置等都通过数据请求来下发,键盘按键数据接口定义如下:
/**
* 键盘按键数据接口
*/
export interface IKeyAttribute {
label: string | Resource;
value?: string;
type?: EKeyType;
fontSize?: number;
fontColor?: string | Color;
backgroundColor?: string | Color;
position?: [number, number, number, number];
}
自定义键盘布局:分为标题栏和键盘两部分,键盘使用Grid布局,每个按键GridItem的值、UI属性和位置都通过数据请求下发,不需要额外计算。
数字键盘为4*3的网格布局,但是大小写键盘和特殊字符键盘的布局为不规则布局,如果设置为4 * 10的网格,有的按键占用1 * 1.5,但是GridItem属性不支持占用非整数列。本文将该场景下将网格拆分为更小的单元,为4 * 20网格布局,每个字母按键占1 * 2,删除按键则占1 * 3,空格则占1 * 10,这样就保证每个按键都要占用整数单元。
Column() { this.titleBar(); Grid() { ForEach(this.items, (item: IKeyAttribute) => { GridItem() { this.myGridItem(item) } .width('100%') .height(this.itemHeight) .rowStart(item?.position?.[0]) .columnEnd(item?.position?.[1]) .columnStart(item?.position?.[2]) .columnEnd(item?.position?.[3]) .backgroundColor(item.backgroundColor) .borderRadius($r("app.integer.key_border_radius")) .onClick(() => { .... }) }, (item: IKeyAttribute, index: number) => JSON.stringify(item) + index) } .margin({ bottom: $r("app.integer.key_board_marin_bottom") }) .columnsTemplate(this.curKeyboardType === EKeyboardType.NUMERIC ? "1fr 1fr 1fr" : "1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr") .rowsTemplate("1fr 1fr 1fr 1fr") // Grid高度均分成4份 .rowsGap(this.rowSpace) // 设置行间距 .columnsGap(this.columnSpace) // 设置列间距 .width('100%') .height(this.itemHeight * this.rowCount + this.rowSpace * (this.rowCount - 1)) } .width('100%') .padding({ left: this.columnSpace, right: this.columnSpace }) .backgroundColor(Color.Black) }
主要是子组件自定义键盘的按键事件如何传递到父组件,可以在父组件定义好键盘按键事件响应函数onKeyboardEvent,传递给子组件,然后子组件按键时调用父组件传递过来的onKeyboardEvent即可。需要注意的是,在子组件中,必须定义inputValue且使用@Link装饰器,这样能保证子组件调用时onKeyboardEvent时inputValue不为空,父子组件数据双向更新。
@Component export struct CustomSafeKeyboardView { @State inputValue: string = ''; @State items: IKeyAttribute[] = numericKeyData; @State curKeyboardType: EKeyboardType = EKeyboardType.NUMERIC; controller: TextInputController = new TextInputController(); /** * 键盘按键事件响应函数 * @param item */ onKeyboardEvent(item: IKeyAttribute) { switch (item.type) { // 输入类型,更新输入内容 case EKeyType.INPUT: this.inputValue += item.value; break; // 删除一个已输入的末尾字符 case EKeyType.DELETE: this.inputValue = this.inputValue.slice(0, -1); break; // 切换数字字符键盘 case EKeyType.NUMERIC: if (this.curKeyboardType !== EKeyboardType.NUMERIC) { this.curKeyboardType = EKeyboardType.NUMERIC; this.items = numericKeyData; } break; // 切换大小写 case EKeyType.CAPSLOCK: if (this.curKeyboardType === EKeyboardType.LOWERCASE) { // 切换大写字母键盘 this.curKeyboardType = EKeyboardType.UPPERCASE; this.items = upperCaseKeyData; } else { // 切换小写字母键盘 this.curKeyboardType = EKeyboardType.LOWERCASE; this.items = lowerCaseKeyData; } break; // 切换特殊字符键盘 case EKeyType.SPECIAL: if (this.curKeyboardType !== EKeyboardType.SPECIAL) { this.curKeyboardType = EKeyboardType.SPECIAL; this.items = specialKeyData; } break; default: console.info(`Sorry, we are out of input type.`); } } /** * 自定义键盘组件Builder */ @Builder customKeyboardBuilder() { CustomKeyboard({ items: this.items, inputValue: this.inputValue, curKeyboardType: this.curKeyboardType, onKeyboardEvent: this.onKeyboardEvent, controller: this.controller }) } build() { Column() { Row() .height($r("app.integer.row_height")) Image($r("app.media.avatar")) .width($r("app.integer.avatar_weight")) .height($r("app.integer.avatar_height")) .objectFit(ImageFit.Fill) Text($r("app.string.account_name")) .fontSize($r("app.integer.text_font_size")) .margin({ top: $r("app.integer.common_margin_padding") }) TextInput({ text: this.inputValue, placeholder: $r("app.string.placeholder"), controller: this.controller })// 绑定自定义键盘 .type(InputType.Password) .customKeyboard(this.customKeyboardBuilder())// 绑定自定义安全键盘 .height($r("app.integer.text_input_height")) .border(null) .margin({ top: $r("app.integer.common_margin_padding") }) Button($r("app.string.login_button_label")) .type(ButtonType.Capsule) .fontSize($r("app.integer.login_button_font_size")) .width($r("app.integer.login_button_width")) .height($r("app.integer.login_button_height")) .margin({ top: $r("app.integer.login_button_margin") }) .backgroundColor(Color.Pink) .onClick(() => { this.controller.stopEditing(); }) } .width($r("app.string.one_hundred_percent")) .height($r("app.string.one_hundred_percent")) .padding($r("app.integer.common_margin_padding")) } }
不涉及
customsafekeyboard // har类型
|---components // 自定义组件
| ---CustomKeyboard.ets
|---model // 模型层
| ---Constants // 定义常量数据
|---CustomSafeKeyboardView.ets // 主页面
也为了积极培养鸿蒙生态人才,让大家都能学习到鸿蒙开发最新的技术,针对一些在职人员、0基础小白、应届生/计算机专业、鸿蒙爱好者等人群,整理了一套纯血版鸿蒙(HarmonyOS Next)全栈开发技术的学习路线【包含了大厂APP实战项目开发】。
gitee.com/MNxiaona/733GH
https://gitee.com/MNxiaona/733GH
1.基本概念
2.构建第一个ArkTS应用
3.……
gitee.com/MNxiaona/733GH
1.应用基础知识
2.配置文件
3.应用数据管理
4.应用安全管理
5.应用隐私保护
6.三方应用调用管控机制
7.资源分类与访问
8.学习ArkTS语言
9.……
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
gitee.com/MNxiaona/733GH
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。