纪念项目开发在获取backspace
监听事件时所遇到的坑。
-
需求
项目的需求是当用户点击backspace
时若当前输入框已无其他输入,则删除前一个联系人(类似于发送信息时删除联系人)。
-
尝试的方法
1.查询RN官方资料
RN官方是未开放出TextInput
输入时,键盘按钮输入的返回事件。具体原因看了一下,是由于安卓监听键盘事件太容易造成监听回调的耗损,故没有开放。所以只有自己动手去监听键盘的点击。
2.监听activity的键盘keyUp事件
可以很容易得到android
开发中监听键盘按钮点击的返回事件。可在MainActivity中添加以下代码获取回调,目前只能获取backspace
的按钮事件,估计android
对于其他按钮的进行了过滤防止回调频繁引起的性能问题。
@Override // <--- Add this method if you want to react to keyUp
public boolean onKeyUp(int keyCode, KeyEvent event) {
KeyEventModule.getInstance().onKeyUpEvent(keyCode, event);
// 有两种方式可选
// 1. 覆盖默认键盘监听事件
// super.onKeyUp(keyCode, event);
// return true;
// 2. 保持原生的键盘监听事件
// return super.onKeyUp(keyCode, event);
// 这里我们直接覆盖已有事件
super.onKeyUp(keyCode, event);
return true;
}
我们可以此时获取事件,通过DeviceEmiiter
返回给JS
端,下面给出一些关键代码:
public void onKeyUpEvent(int keyCode, KeyEvent keyEvent) {
if (mJSModule == null) {
//mReactContext在初始化nativeModulesPackage时传递过来
mJSModule = mReactContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
}
//发送监听给JS端
mJSModule.emit("onKeyUp", getJsEventParams(keyCode, keyEvent, null));
};
private WritableMap getJsEventParams(int keyCode, KeyEvent keyEvent, Integer repeatCount) {
WritableMap params = new WritableNativeMap();
int action = keyEvent.getAction();
if (keyEvent.getAction() == KeyEvent.ACTION_MULTIPLE && keyCode == KeyEvent.KEYCODE_UNKNOWN) {
String chars = keyEvent.getCharacters();
if (chars != null) {
params.putString("characters", chars);
}
}
if (repeatCount != null) {
params.putInt("repeatcount", repeatCount);
}
params.putInt("keyCode", keyCode);
params.putInt("action", action);
return params;
}
如未使用的React-Native-Navigation
,则项目已经成功达成我们的需求了。但在使用React-Native-Navigation
之后,死活无法获取键盘输入时的回调。
3.使用React-Native-Navigation
后续的坑
由于一直无法获取监听回调,理了一下可能的原因
- 该监听事件被安卓原生所截取了,未暴露给用户层。
- 该监听事件被
React-Native-Navigation
所截取了,未暴露给用户层
由于当时把精力集中在第一点上,在和同事讨论之后,他的建议是能在原生层获取当前viewID
然后在原生层进行包装warpper
手动截取其keyUp
事件。所以我们通过以下方式在JS层
传递viewID给原生层,然后利用原生的findViewById
获取当前view
,然后我们即可为所欲为。以下为此方法的代码:
import { TextInput,findNodeHandle } from 'React-Native';
...
render() {
return (
<View>
<TextInput ref="textInput">
...
</TextInput >
</View>
);
},
somethingLikeComponentDidMount() {
const customViewNativeID = findNodeHandle(this.refs.textInput);
// 将id传给原生层
}
但是。。。。。在原生层通过findViewById
却一直返回null
,想了很多办法,还是获取为null
,最后不得不放弃该思路,理了一下第二条思路。会不会是React-Native-Navigation
框架使用了新的activity
?
查看了React-Native-Navigation
的源码,果然。。。
在我们使用Start***App
方法之后,React-Native-Navigation
会push
进入其封装好的navigationActivity
,且在该activity
中已将该方法封装好。我们只需要修改源码,把监听发送出来即可。但还是感觉贼不爽。至此,终于把主要的坑填完了。。。
PS:
1.改源码真的是今后维护的大坑 😭
2.必须使用push
的界面才能进行回调,看了React-Native-Navigation
的源码,modal
出来的界面,会new
一个新的无法监听的activity
无法监听其键盘回调事件 。
网友评论