React NativeReactNativeReactNative开发

使用React Native自定义安全键盘(iOS和Androi

2017-05-04  本文已影响2901人  羽纱

自定义键盘的实现效果如下:

iOS端:

ios-keyboard.gif
Android端:
android-keyboard.gif

npm仓库地址

react-native-yusha-customkeyboard

yarn add react-native-yusha-customkeyboard
react-native link

实现功能(iOS和Android):

大致思路

1、如何隐藏系统键盘
用RN为iOS和Android双平台共用一套自定义键盘,使用RN的TextInput作为输入框,这样TextInput该怎么使用就怎么使用,因此问题的关键就在于如何隐藏系统键盘。在iOS中使用inputView可以轻松实现自定义键盘,在Android中自定义键盘并非像iOS那么直接,需要手动隐藏系统键盘,然后监听输入框的焦点事件来控制自定义键盘的显示和隐藏。
可以看以下两个示例大致了解下:
iOS自定义键盘
Android 自定义键盘实现

Android中自定义键盘有一个让人容易误解的地方,就是KeyboardView。可以在Android 自定义键盘实现Demo中看到有hideSystemSoftKeyboard方法,用来把EditText的系统键盘给隐藏,然后再使用KeyboardView加入到视图的底部布局中,KeyboardView使用KeyboardView.OnKeyboardActionListener来监听键盘点击,使用Keyboard来给定键盘布局(使用XML描述布局),然后可以动态修改KeyboardKeyboardView.OnKeyboardActionListener来实现不同的自定义键盘。由此可见,使用RN做自定义键盘在hideSystemSoftKeyboard后就可以打止了,不需要使用KeyboardView,而是使用ReactRootView,然后在RN中绘制键盘。

2、自定义键盘与原生输入组件如何交互

时序图如下:

Paste_Image.png

RN中文网的自定义键盘的GitHub地址:https://github.com/reactnativecn/react-native-custom-keyboard
关于ReactTag的基本原理(iOS版):http://awhisper.github.io/2016/07/02/ReactNative%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%902/

绘制

将上面的流程和代码弄清后就只剩下RN的键盘界面问题了。

数字键盘的布局和绘制:
参考代码:https://github.com/beefe/react-native-keyboard

字母键盘的布局示意图:

image.png

字符键盘的布局示意图:

image.png

字母和符号键盘的Tip绘制:
最初想法:每个key都为一个单独的component,里面有个TouchableHighlight按钮和与按钮并级的Tip组件,在onPressIn和onPressOut之间控制Tip的显示与隐藏。

不可行:以上方案在Android端不可行,因为Android中RN不能使用overflow:visible属性,在0.41版本中可以使用FlatUIImplement实现overflow:visible属性,但是在0.42及以上版本使用会报错(不过现在解决了,我没试)。

曲线救国想法:使用measureLayout得到key相对keyboard的位置,然后在keyboard层级绘制Tip,而不在key组件中绘制Tip。这个方案基本可行,但是在Android端还是需要解决以下问题:
1、Tip可能会超过keyboard的边界,因此第一行还是会被截掉,所以需要把键盘的高度要加高一些以容纳第一行的Tip。
2、keyboard的背景色会遮挡下层视图,所以要对keyboard的背景做透明。
3、keyboard加高的部分会遮挡下层视图对手势的响应,所以对加高的部分要放弃事件响应。

解答参考了stackoverflow上的提问:Element overflow hidden in React-Native Android

绘制难点:
iOS端Tip外形的绘制:使用react-native-svg绘制,我的绘制代码
Android阴影的实现:使用以react-native-svg为基库做成的react-native-shadow

注:我并没有在Android中使用阴影样式,而是仿照f8app的写法在不同平台使用不同样式

性能优化

因为字母和字符键盘一次性绘制了30多个按钮在屏幕上,会导致在低端Android机能感觉到卡顿(调成Debug模式会很明显,在Dev下打开'Show Perf Monitor'会发现首屏渲染时JS线程掉帧很明显),我在这做了个测试:一次性渲染40个按钮,可以运行看一下卡顿情况。
因此渲染出的数字、字母和字符键盘的DOM分别要被缓存起来,这样才不会在频繁切换键盘时感觉到卡顿。
如果首屏出现的是数字键盘,那么字母键盘和字符键盘就不应该被放在渲染树中,做到用到特定键盘时再去加载这个键盘。

根据React 源码剖析系列 - 不可思议的 react diff,要做到高效的渲染尽量不能改变Dom树的结构,React并没有提供removeViewaddView之类的方法(当然你可以通过带 _ 的私有方法实现),Element(使用JSX或者React. createElement创建出来的)其实并不占多大空间,真正渲染的是DOM(可以通过ref获取),使用DisplayView可以控制DOM的隐藏和显示,让视图在第一次使用时才在DOM树创建,在隐藏和显示时不用改变DOM树的结构。

示例代码

customKeyboard

npm库

react-native-yusha-customKeyboard

安利两个工具

react-native-storybook
UI组件的开发工具,可以浏览组件库,查看各个组件的各个状态,以及开发和测试组件。

react-devtools

image.png
上一篇下一篇

猜你喜欢

热点阅读