场景:android 应用监听输入法按键事件【例如搜索和回车键等】的整个流程分析

android 应用监听输入法按键事件【比如搜索和回车键等】的整个流程分析

继承于InputMethodService类的服务代码如下:

int keyCode = sKey.getKeyCode();

KeyEvent eDown = new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,

keyCode, 0, 0, 0, 0, KeyEvent.FLAG_SOFT_KEYBOARD);

KeyEvent eUp = new KeyEvent(0, 0, KeyEvent.ACTION_UP, keyCode,

0, 0, 0, 0, KeyEvent.FLAG_SOFT_KEYBOARD);

onKeyDown(keyCode, eDown);

onKeyUp(keyCode, eUp);

上面的代码:把有关按键下发给应用,即应用监听输入法按键事件

@Override

public boolean onKeyDown(int keyCode, KeyEvent event) {

if (processKey(event, 0 != event.getRepeatCount())) return true;

return super.onKeyDown(keyCode, event);

}

@Override

public boolean onKeyUp(int keyCode, KeyEvent event) {

if (processKey(event, true)) return true;

return super.onKeyUp(keyCode, event);

}

上面的down和up,我们重点看onKeyUp,跟踪下日志,是下面直接返回true了

if (processKey(event, true)) return true;

进入该方法,在该方法里面有如下代码为其覆盖代码:

if (processFunctionKeys(keyCode, realAction)) {

return true;

}

再进入该方法processFunctionKeys,跟踪其走入了下面代码:

if (keyCode == KeyEvent.KEYCODE_ENTER) {

if (!realAction){

Log.d(TAG,"processFunctionKeys call KEYCODE_ENTER return");

return true;

}

sendKeyChar('\n');

return true;

}

因为上面realAction为传进来的true,所以执行了如下

sendKeyChar('\n');

进入该方法,该方法在InputMethodService中

public void sendKeyChar(char charCode) {

switch (charCode) {

case '\n': // Apps may be listening to an enter key to perform an action

if (!sendDefaultEditorAction(true)) {

sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);

}

break;

default:

// Make sure that digits go through any text watcher on the client side.

if (charCode >= '0' && charCode <= '9') {

sendDownUpKeyEvents(charCode - '0' + KeyEvent.KEYCODE_0);

} else {

InputConnection ic = getCurrentInputConnection();

if (ic != null) {

ic.commitText(String.valueOf((char) charCode), 1);

}

}

break;

}

}

因为传进入的是'\n',所以执行了如下:

case '\n': // Apps may be listening to an enter key to perform an action

if (!sendDefaultEditorAction(true)) {

sendDownUpKeyEvents(KeyEvent.KEYCODE_ENTER);

}

break;

看上面注释:// Apps may be listening to an enter key to perform an action,很清楚吧,呵呵,来看看这个方法吧

public boolean sendDefaultEditorAction(boolean fromEnterKey) {

EditorInfo ei = getCurrentInputEditorInfo();

if (ei != null &&

(!fromEnterKey || (ei.imeOptions &

EditorInfo.IME_FLAG_NO_ENTER_ACTION) == 0) &&

(ei.imeOptions & EditorInfo.IME_MASK_ACTION) !=

EditorInfo.IME_ACTION_NONE) {

// If the enter key was pressed, and the editor has a default

// action associated with pressing enter, then send it that

// explicit action instead of the key event.

InputConnection ic = getCurrentInputConnection();

if (ic != null) {

ic.performEditorAction(ei.imeOptions&EditorInfo.IME_MASK_ACTION);

}

return true;

}

return false;

}

上面这个方法只是通知:让编辑器执行它,表示它可以做一个动作:

/**

* Have the editor perform an action it has said it can do.

*/

public boolean performEditorAction(int editorAction);

/**

* Set of bits in {@link #imeOptions} that provide alternative actions

* associated with the "enter" key. This both helps the IME provide

* better feedback about what the enter key will do, and also allows it

* to provide alternative mechanisms for providing that command.

*/

public static final int IME_MASK_ACTION = 0x000000ff;

我们来看这个方法EditableInputConnection中,有关为什么是EditableInputConnection看我之前的帖子就会明白了

@Override

public boolean performEditorAction(int actionCode) {

if (DEBUG) Log.v(TAG, "performEditorAction " + actionCode);

mTextView.onEditorAction(actionCode);

return true;

}

一般应用程序想要监听回车或搜索按键则,如下写法:

edittext.setOnEditorActionListener(new TextView.OnEditorActionListener() {

@Override

public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

/*判断是否是“GO”键*/

if(actionId == EditorInfo.IME_ACTION_GO){

edittext.setText("success");

return true;

}

return false;

}

});

上面这个调用的是TextView中的接口

/**

* Interface definition for a callback to be invoked when an action is

* performed on the editor.

*/

public interface OnEditorActionListener {

/**

* Called when an action is being performed.

*

* @param v The view that was clicked.

* @param actionId Identifier of the action. This will be either the

* identifier you supplied, or {@link EditorInfo#IME_NULL

* EditorInfo.IME_NULL} if being called due to the enter key

* being pressed.

* @param event If triggered by an enter key, this is the event;

* otherwise, this is null.

* @return Return true if you have consumed the action, else false.

*/

boolean onEditorAction(TextView v, int actionId, KeyEvent event);

}

上面的又是怎么实现的呢?

/**

* Set a special listener to be called when an action is performed

* on the text view. This will be called when the enter key is pressed,

* or when an action supplied to the IME is selected by the user. Setting

* this means that the normal hard key event will not insert a newline

* into the text view, even if it is multi-line; holding down the ALT

* modifier will, however, allow the user to insert a newline character.

*/

public void setOnEditorActionListener(OnEditorActionListener l) {

if (mInputContentType == null) {

mInputContentType = new InputContentType();

}

mInputContentType.onEditorActionListener = l;

}

我们看到了OnEditorActionListener l赋值给了mInputContentType.onEditorActionListener

那么我们再回到上面EditableInputConnection中的方法:

@Override

public boolean performEditorAction(int actionCode) {

if (DEBUG) Log.v(TAG, "performEditorAction " + actionCode);

mTextView.onEditorAction(actionCode);

return true;

}

进入如下方法:

mTextView.onEditorAction(actionCode);

public void onEditorAction(int actionCode) {

final InputContentType ict = mInputContentType;

if (ict != null) {

if (ict.onEditorActionListener != null) {

if (ict.onEditorActionListener.onEditorAction(this,

actionCode, null)) {

return;

}

}

看到了吧,之前放入mInputContentType的onEditorActionListener现在赋值给了InputContentType ict,然后执行了

ict.onEditorActionListener.onEditorAction(this,

actionCode, null)

现在我们明白了吧,搜索和回车等等按键就是这么实现回调的

android 输入法 监听,android 监听 输入法相关推荐

  1. android 输入法 确定按钮,Android项目:输入法软键盘显示/隐藏的监听和控制,InputMethodManager用法研究...

    在项目开发中,用到编辑框的地方经常涉及到要监听或者控制软键盘的显示/隐藏状态.本以为这是很容易解决的一个小问题,没想到当初碰到这个问题才明白还得花点小心思才能整好.现将针对软键盘的显示/隐藏状态的监听 ...

  2. android 键盘点击事件监听事件,Android 键盘事件触发以及监听

    一.Android 手动显示和隐藏软键盘 如果输入法在窗口上已经显示,则隐藏,反之则显示 InputMethodManager imm = (InputMethodManager) getSystem ...

  3. Android模拟键盘和键盘监听的一些调研

    1           键盘监控分析 Android的按键产生的是一个KeyEvent,这个KeyEvent只能被最上层focus窗口的activity和view得到. 所有的按键事件都会首先触发pu ...

  4. 对EditText的软键盘进行监听-----android:imeOptions

    在android发开过程中,有时候需要对EditText的软键盘进行监听. 当点击软键盘回车位置按键的时候,需要实现 完成.前进.下一项.搜索.发送或其他功能,这就需要开发者对软键盘回车的点击事件进行 ...

  5. Android模拟键盘和键盘监听

    1           键盘监控分析 Android的按键产生的是一个KeyEvent,这个KeyEvent只能被最上层focus窗口的activity和view得到. 所有的按键事件都会首先触发pu ...

  6. android 监听物理返回键,Android应用开发之react-native 监听Android物理返回键

    本文将带你了解Android应用开发之react-native 监听Android物理返回键,希望本文对大家学Android有所帮助. 1. componentWillMount(){         ...

  7. Android事件的响应,Android 开发事件响应之基于监听的事件响应

    Android 开发事件响应之基于监听的事件响应 本文将介绍Android 操作系统如何通过监听来实现对事件的响应. Android 开发事件响应之基于监听的事件响应 背景介绍 Android 开发事 ...

  8. Android 监听 Android中监听系统网络连接打开或者关闭的实现代码

    本篇文章对Android中监听系统网络连接打开或者关闭的实现用实例进行了介绍.需要的朋友参考下 很简单,所以直接看代码 复制代码 代码如下: package xxx; import android.c ...

  9. android edittext 光标监听,Android EditText监听器,用于光标位置更改

    我有一个EditText对话框. EditText在创建时已经填充.当用户将光标放置在文本的特定部分或其附近时,Toast将弹出. 我的问题是监听光标位置的变化.另一个post提出同样的问题,并且接受 ...

  10. android 窗口监听按键,Android编程实现Dialog窗体监听的方法

    本文实例讲述了Android编程实现Dialog窗体监听的方法.分享给大家供大家参考,具体如下: 今天做了一个Dialong窗体监听包括窗体内的xml监听. 效果图: test.class代码 pac ...

最新文章

  1. HTML常见标签易踩坑笔记(一)
  2. LSTM内部实现原理详解
  3. 三框架:使用数据源dbcp注意
  4. hbase开发环境搭建及运行hbase小实例(HBase 0.98.3新api)
  5. Java单向链表操作详解
  6. JSON有关的一道题
  7. linux18.04忘记账号密码,Ubuntu18.04忘记超级用户root密码,重新设置密码
  8. Visual Studio无法推送提交到Github的解决方法
  9. 非对称加密算法RSA
  10. 逆向研究QCA9563固件,查看和修改GPIO定义
  11. jeb java_jeb2 java 脚本插件
  12. wincemobile的GPS开发
  13. Scratch(五):Scratch小游戏之超级玛丽
  14. 计算机作业word电子杂志,怎么用Word文档制作电子杂志目录
  15. 帝国cms栏目添加二级域名
  16. NFDATA定义的一个细节
  17. 论文阅读(8)Cool your jets:海洋无脊椎动物的生物喷射推进(2021)
  18. 软件工程第一章绪论————(2019.12.27学习笔记)
  19. JavaScript基础——使用Canvas画图
  20. Bootstrap 4 Alpha 4发布

热门文章

  1. Rancher 1.6发布:EBS支持、密文管理和CLI增强
  2. 《CSS揭秘》:菱形图片
  3. Python asyncio库的学习和使用
  4. android实用测试方法之Monkey与MonkeyRunner
  5. 艰难的时候总会过去,只要你能坚持下来~
  6. 11-6-线程的概念
  7. 2-6 刮刮乐和双色球
  8. python自助电影售票机_手把手教你用python抢票回家过年(代码简单)
  9. 计算机毕业设计中用Java实现商场库存清单案例
  10. java linux driver,JAVA:使用GeckoDriver在Linux上运行Selenium测试:驱动程序不可执行