android webview软键盘监听删除键、回车键、其他键

android webview软键盘监听删除键、回车键、其他键

终于有时间来写文章了,头一回发表,文章连贯性可能无法保障,大家勉强看一下吧

今天说点关于android 和 webview 沟通的时候,需要监听软键盘的按键事件的问题

情境描述:由于js在部分手机上(比如华为青春版P8)无法监听到删除键,引起项目部分功能无法实现

解决思路:js 与android 互相沟通 就不多说了,网上一搜一大片,重点说一下 我的解决办法,之前在网上搜了一下,说的是andriod跟webview交互的时候,就把输入法管理 权交给webview了,从自己的界面代码是没有办法去监听软键盘的,所以想到了,看能不能去拦截下 输入链接桥梁,然后再拦截事件转交给 js,这样那些js无法监听软键盘的事件就ok了,

 6.0手机以上 你可以采用像网上说的,自定义Webview,继承Webview,自定义里面的其他覆写方法不多说,网上一搜一大片,重点是复写onCreateInputConnection(EditorInfo outAttrs)方法,返回一个InputConnection输入法链接桥梁,然后对这个输入法链接桥梁 做一些你要干的事情,代码如下:

public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   
   return new MyInputConnection(super.onCreateInputConnection(outAttrs),//用父类的输入链接桥梁 转换成自己的,以便于对输入事件拦截,

         true,onItemClickCallBackI);  //onItemClickCallBackI是自定义的一个回调接口,没什么可说的 
}                 

public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   
   return new MyInputConnection(super.onCreateInputConnection(outAttrs),//用父类的输入链接桥梁 转换成自己的,以便于对输入事件拦截,

         true,onItemClickCallBackI);  //onItemClickCallBackI是自定义的一个回调接口,没什么可说的 

public class MyInputConnection extends InputConnectionWrapper {
   private OnItemClickCallBackI onItemClickCallBackI;
   public MyInputConnection(InputConnection target, boolean mutable,OnItemClickCallBackI onCallBackI) {
      super(target, mutable);
      if(onCallBackI!=null){
         this.onItemClickCallBackI=onCallBackI;
      }
   }

   @Override
   public Handler getHandler() {
      return new Handler();
   }

   @Override
   public boolean sendKeyEvent(KeyEvent event) {
      if(this.onItemClickCallBackI!=null){
         onItemClickCallBackI.callFirstBack(event);//按键事件回调
      }

      return super.sendKeyEvent(event);
   }

   @Override
   public boolean deleteSurroundingText(int beforeLength, int afterLength) {
      // magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
      if (beforeLength == 1 && afterLength == 0) {
         // backspace
         return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
               && sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
      }

      return super.deleteSurroundingText(beforeLength, afterLength);
   }

}

super.onCreateInputConnection(outAttrs) 华为青春版P8这个方法直接就返回空了,根本无法拦截

这就尴尬了,也一直在去搜索这方面知识,奈何时间又短,项目又紧张,根本没有时间去看系统代码,所以只能想其他办法,后面看到了EditText是如何拦截输入内容的,然后觉得如果将整个webview假设成为EditText有没有可能,没想到一试,还真行,代码如下:

    

@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
   super.onCreateInputConnection(outAttrs);
   return new MyInputConnection(new InputView(MyWebView.this,false,onItemTextClickCallBackI),
         true,onItemClickCallBackI);//InputView自己定义的继承基础输入链接桥梁类,


}
public class InputView extends BaseInputConnection {
   private OnItemClickCallBackI onItemTextClickCallBackI;

   public InputView(View targetView, boolean fullEditor,OnItemClickCallBackI textClickCallBackI) {
      super(targetView, fullEditor);
      this.onItemTextClickCallBackI=textClickCallBackI;
   }

   @Override
   public boolean commitText(CharSequence text, int newCursorPosition) {
      //System.out.println("截获的文字   :"+text);
      onItemTextClickCallBackI.callFirstBack(text);//文字拦截回调

      return true;
   }
}
public class MyInputConnection extends InputConnectionWrapper {
   private OnItemClickCallBackI onItemClickCallBackI;
   public MyInputConnection(InputConnection target, boolean mutable,OnItemClickCallBackI onCallBackI) {
      super(target, mutable);
      if(onCallBackI!=null){
         this.onItemClickCallBackI=onCallBackI;
      }
   }

   @Override
   public Handler getHandler() {
      return new Handler();
   }

   @Override
   public boolean sendKeyEvent(KeyEvent event) {
      if(this.onItemClickCallBackI!=null){
         onItemClickCallBackI.callFirstBack(event);//事件拦截回调
      }

      return super.sendKeyEvent(event);
   }

   @Override
   public boolean deleteSurroundingText(int beforeLength, int afterLength) {
      // magic: in latest Android, deleteSurroundingText(1, 0) will be called for backspace
      if (beforeLength == 1 && afterLength == 0) {
         // backspace
         return sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
               && sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
      }

      return super.deleteSurroundingText(beforeLength, afterLength);
   }

}
为什么去写了两个回调方法,一个是回调输入的文字,一个是回调软键盘的事件,当你去看到EditText 写拦截事件的时候,也没有整这么多内部类,原因就是以为webview毕竟不是EditView,不这么搞,要出事,
MyInputConnection 主要是去拦截软键盘的事件,
InputView 主要是去拦截输入的内容,

可能你只需要拦截软键盘事件,拦截内容干什么,接下来,你就明白了,

由于webview毕竟不是EditView,而且又是自定义的输入桥梁,当你在6.0以上系统是没有问题的,可是等到了6.0以下包括6.0,你会发现,你拦截的这个输入桥梁,根本无法输入汉字,英文 又是完全正常,这就尴尬了,好比以上的代码都是白费,其实不然,换个思路补救一下就OK,这就是为什么会有 

InputView 这个类里面的 onItemTextClickCallBackI.callFirstBack(text);方法回调了
在回调的时候,将你拦截到的内容,传给js,让JS动态把这些字设到相应的控件上

这样中文 英文 都没有问题了,当然了,如果你有时间,可以去研究下系统源码,会有更好的处理中文和英文的办法

总的来说,解决办法就是 重新搭建 android 与webview的输入链接桥梁,拦截输入事件和内容,回调给js,这样在目前我实测了大量的手机下是没有问题的,

希望以上内容对您有所帮助,如果有更好的办法,还请指点

你可能感兴趣的:(android,webview)