Android控件TextView的实现原理分析
作者:网络转载 发布时间:[ 2013/5/16 10:28:29 ] 推荐标签:
参数event描述的是窗口接收到的键盘事件,另外一个参数sendDone表示该键盘事件处理完成后,是否需要向系统的输入管理器发送一个通知。
ViewRoot类的成员变量mView描述的是窗口的顶层视图,即它指向的是一个DecorView对象,ViewRoot类的成员函数deliverKeyEvent首先是调用它的成员函数dispatchKeyEventPreIme来让它优先于输入法处理参数event所描述的键盘事件。如果这个DecorView对象的成员函数dispatchKeyEventPreIme的返回值handled等于true,那么说明参数event所描述的键盘事件已经处理完毕,即ViewRoot类的成员函数deliverKeyEvent不用往下执行了。在这种情况下,如果参数sendDone的值等于true,那么ViewRoot类的成员函数deliverKeyEvent在返回之前,还会调用成员函数finishInputEvent来通知系统的输入管理器,当前激活的窗口已经处理完成刚刚发生的键盘事件了。在接下来的Step 2到Step 4中,我们再详细分析键盘事件优先于输入法分发给窗口处理的过程。
假设窗口不在输入法前面拦截参数event所描述的键盘事件,接下来ViewRoot类的成员函数deliverKeyEvent会将该键盘事件分发给输入法处理,这个分发过程如下所示:
1. 调用InputMethodManager类的静态成员函数peekInstance获得一个类型为InputMethodManager输入法管理器imm;
2. 调用ViewRoot类的成员函数enqueuePendingEvent将参数event所描述的键盘事件缓存起来,等到输入法处理完成该键盘事件之后,再继续对它进行处理;
3. 调用第1步获得的输入法管理器imm的成员函数dispatchKeyEvent来将参数event所描述的键盘事件分发给输入法处理。
这里有两个地方是需要注意的。第一个地方是只有当前窗口正在显示输入法的情况下,ViewRoot类的成员函数deliverKeyEvent才会将参数event所描述的键盘事件分发给输入法处理,这是通过检查ViewRoot类的成员变量mLastWasImTarget的值是否等于true来确定的。第二个地方是在将参数event所描述的键盘事件分发给输入法处理时,ViewRoot类的成员函数deliverKeyEvent会同时传递一个类型为InputMethodCallback的回调接口给输入法,以便输入法处理完成参数event所描述的键盘事件之后,可以调用这个回调接口的成员函数finishedEvent来向窗口发送一个键盘事件处理完成通知。这个类型为InputMethodCallback的回调接口保存在ViewRoot类的成员变量mInputMethodCallback中,当它的成员函数finishedEvent被调用的时候,它会调用ViewRoot类的成员函数deliverKeyEventToViewHierarchy来继续将参数event所描述的键盘事件分发给窗口处理。
如果窗口当前不需要与输入法交互,即ViewRoot类的成员变量mLastWasImTarget的值等于false,那么ViewRoot类的成员函数deliverKeyEvent会直接调用成员函数deliverKeyEventToViewHierarchy来将参数event所描述的键盘事件分发给窗口处理。
接下来,我们先析窗口在输入法之前处理键盘输入的过程,接着再分析窗口在输入法之后处理键盘输入的过程。
从前面的分析可以知道,ViewRoot类的成员函数deliverKeyEvent是通过调用DecorView类的成员函数dispatchKeyEventPreIme来将获得的键盘输入优先于输入法分发给窗口处理的。DecorView类的成员函数dispatchKeyEventPreIme是从父类ViewGroup继承下来的,因此,接下来我们继续分析ViewGroup类的成员函数dispatchKeyEventPreIme的实现。
Step 2. ViewGroup.dispatchKeyEventPreIme
[java] view plaincopyprint?
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
......
// The view contained within this ViewGroup that has or contains focus.
private View mFocused;
......
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
return super.dispatchKeyEventPreIme(event);
} else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
return mFocused.dispatchKeyEventPreIme(event);
}
return false;
}
......
}
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
......
// The view contained within this ViewGroup that has or contains focus.
private View mFocused;
......
@Override
public boolean dispatchKeyEventPreIme(KeyEvent event) {
if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {
return super.dispatchKeyEventPreIme(event);
} else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {
return mFocused.dispatchKeyEventPreIme(event);
}
return false;
}
......
}
这个函数定义在文件frameworks/base/core/java/android/view/ViewGroup.java中。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11