美文网首页
React Native Android 安卓监听键盘backs

React Native Android 安卓监听键盘backs

作者: SunnyEver0 | 来源:发表于2018-04-07 22:46 被阅读323次

    纪念项目开发在获取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-Navigationpush进入其封装好的navigationActivity,且在该activity中已将该方法封装好。我们只需要修改源码,把监听发送出来即可。但还是感觉贼不爽。至此,终于把主要的坑填完了。。。
    PS:
    1.改源码真的是今后维护的大坑 😭
    2.必须使用push的界面才能进行回调,看了React-Native-Navigation的源码,modal出来的界面,会new一个新的无法监听的activity无法监听其键盘回调事件 。

    相关文章

      网友评论

          本文标题:React Native Android 安卓监听键盘backs

          本文链接:https://www.haomeiwen.com/subject/coruhftx.html