React Native 自定义软键盘

2024-06-04

很多手机应用都有自定义键盘的需求,本文将介绍如何在 React Native 中,为 iOS 和 Android 两端的应用编写自定义键盘。

准备工作

基本的 React Native 起码要会吧?起项目直接用最新的版本,具体请看React Native 官网。 推荐把这个单独功能抽成 NPM 包。

shell

创建出来文件目录是这样的:

  • android
  • ios
  • src
  • package.json
  • react-native-custom-keyboard.podspec

注意一点,如果在已有项目中运行上述命令,会直接在 package.json 对该项目进行软链接,由于 Metro 不支持软连接,请把相关引用改成硬连接。

json

思路介绍

为了保证UI一致性,整个 UI 应该在 JavaScript 端构建。由于 React Native 的 TextInput 并未提供简易的软键盘替换功能,所以,我需要进行原生开发。 我预想的 API 是设计一个 KeyboardProvider 包裹 TextInput,类似这样:

tsx

当 TextInput 聚焦的时候,软键盘处会弹出 <CustomKeyboard /> 中的内容。

下面,开始思路介绍和代码展示。

JavaScript 代码

首先,先定义一下 JS 端跟原生的交互接口。我们需要有操作可以把 React 元素放入软键盘中;还需要在销毁TextInput销毁时,删除已注册元素的操作;最后,还有触发字符增减的操作。

CustomKeyboardModule

为了满足上述条件,CustomKeyboardModule 接口定义成这样。

ts

先解释一下其中的参数。

  • tag: TextInput 在 React 中的 id,通过它可以在原生代码找到指定的 TextInput 的引用实例。
  • name: 注册视图表中的视图唯一标识,就是通过 React Native 自带的通信机制,可以在原生端拿到用 React 写的自定义键盘组件。
  • width 和 height: 软键盘的宽高。如果你没有特殊化需求,其实这个可以设个默认值就行。

KeyboardProvider 设计思路

KeyboardProvider 按照上述的第一部分 API 设计,应该设计成这样。

ts

具体的组件设计思路是用 cloneElementchildren 重定义一次,拿到 TextInput 在 React 中的实例,通过 findNodeHandle,找到这个 TextInput 的 tag,然后再调用 customKeyboardModule.install 绑定一下。

tsx

到这里,还需要再给 KeyboardProvider 添加注册函数。

tsx

iOS 接口

打开 ios 目录会发现命令帮你创建了一组类文件 CustomKeyboard.h 和 CustomKeyboard.mm ,后续的代码只会在 CustomKeyboard.mm 文件中修改。现在我需要在原生端创建接口以便 JS 端可以调用。

Cxx

install

在 iOS 中,TextField 和 TextView 提供了 inputView 属性,它可以帮助你快速自定义软键盘。 在 React Native 中,TextInput 组件基于 RCTBaseTextInputView ,派生出了两个类 RCTSinglelineTextInputView 和 RCTMultilineTextInputView ,分别封装了 TextField 和 TextView。我可以通过 RCTBaseTextInputView.backedTextInputView.inputView 可以直接拿到软键盘属性,而不用区分他们是什么类型。之后,将软键盘组件实例化并设置给该属性。

Cxx

uninstall

卸载操作需要把 RCTBaseTextInputView.backedTextInputView.inputView 设为 nil

Cxx

append

RCTBaseTextInputView.backedTextInputView 把 singleline 和 mutiline 的一些共有操作抽象了出来,为了可以让新增字符在光标后面增加,需要通过 selectedTextRange 定位光标位置,并把按键对应的字符填入。

Cxx

backspace

回退操作也类似,光标如果是没有选择的,那么把起点往左移一格,然后移除。

Cxx

以上,就完成了 iOS 端原生模块的定义。

Android 接口

打开 android 目录会发现命令帮你创建了一个 Android Project,模块的代码在 src/main/java/com/customkeyboard/CustomKeyboardModule.java 。只用改这部分的代码就可以了。

Java

install

在 Android 中,TextInput 对应的实体类是 ReactEditText ,他提供 InputConnection 进行输入监控。如果要自定义键盘,可以调用 ReactEditText.setShowSoftInputOnFocus(false) ,让系统键盘不显示,并显示当前的键盘。

这里,先给出一些辅助方法。

java

最后, install 的代码是这样的。

java

uninstall

uninstall 的代码是这样的。

Java

append

append 的代码是这样的,跟 iOS 差不多。

Java

backspace

backspace 的接口是这样的,跟 iOS 差不多。

Java

总结

给大家介绍了如何使用 React Native 进行自定义键盘,如果对你有帮助,点赞,收藏起来!