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有没有可能,没想到一试,还真行,代码如下:

    

@Overridepublic 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,这样在目前我实测了大量的手机下是没有问题的,

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

更多相关文章

  1. Android - 事件分发机制
  2. Android 解决Dialog导致软键盘无法隐藏的问题
  3. Android应用程序键盘(Keyboard)消息处理机制分析(16)
  4. android 4.0.x Home键事件拦截/监听
  5. Android如何快速打开系统软键盘和关闭系统软键盘
  6. Android:处理触摸事件
  7. android 自定义软键盘

随机推荐

  1. 《疯狂Android讲义》第4版 代码
  2. android新闻端demo
  3. Android(安卓)ButterKnife框架的使用方法
  4. Android下的摄像头驱动开发
  5. android ListView 九大重要属性详细分析
  6. android开发笔记之2012版辅助开发工具包(A
  7. [Android(安卓)Studio 权威教程]Windows下
  8. 2012版辅助开发工具包(ADT)新功能特性介绍
  9. [置顶] TextView属性大全
  10. 向Android社区贡献代码过程详解