case KeyEvent.KEYCODE_DPAD_LEFT:
direction = View.FOCUS_LEFT;
break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
direction = View.FOCUS_RIGHT;
break;
case KeyEvent.KEYCODE_DPAD_UP:
direction = View.FOCUS_UP;
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
direction = View.FOCUS_DOWN;
break;
}
if (direction != 0) {
View focused = mView != null ? mView.findFocus() : null;
if (focused != null) {
View v = focused.focusSearch(direction);
......
if (v != null && v != focused) {
......
focusPassed = v.requestFocus(direction, mTempRect);
}
......
}
}
}
}
} finally {
if (sendDone) {
finishInputEvent();
}
......
}
}
......
}
这个函数定义在文件frameworks/base/core/java/android/view/ViewRoot.java中。
ViewRoot类的成员函数deliverKeyEventToViewHierarchy首先将参数event所描述的键盘事件交给当前激活的窗口的顶层视图来处理,这是通过调用ViewRoot类的成员变量mView所描述的一个DecorView对象的成员函数dispatchKeyEvent来实现的。
如果当前激活的窗口的顶层视图在处理完成参数event所描述的键盘事件之后,希望该键盘事件还能继续被ViewRoot类的成员函数deliverKeyEventToViewHierarchy处理,那么前面调用DecorView类的成员函数dispatchKeyEvent得到的返回值keyHandled的值就会等于false。在这种情况下,如果参数event描述的是一个按下的键盘事件,即变量isDown的值等于true,那么ViewRoot类的成员函数deliverKeyEventToViewHierarchy就会继续检查参数event描述的是否是一个DPAD事件。如果是的话,那么就可能需要改变窗口当前的焦点子视图。
如果参数event描述的是一个DPAD事件,那么最终得到的变量direction的值就不会等于0,并且它描述的是当前按下的是哪一个方向的DPAD键。假设这时候窗口已经有一个焦点子视图,即调用ViewRoot类的成员变量mView所描述的一个DecorView对象的成员函数findFocus的返回值focused不等于null,那么接下来就要根据变量direction的值来决定下一个焦点子视图是谁。例如,假设变量direction的值等于View.FOCUS_LEFT,那么就表示在当前的焦点子视图focused的左边查找一个最靠近的子视图作为下一个焦点子视图,这是通过调用当前焦点子视图focused的成员函数focusSearch来实现的。
一旦找到了下一个焦点子视图v,并且该子视图不是当前的焦点子视图focused,那么ViewRoot类的成员函数deliverKeyEventToViewHierarchy就需要将子视图v设置为焦点子视图,这是通过调用变量v所描述的一个View对象的成员函数requestFocus来实现的。
通过前面的操作,参数event所描述的键盘事件就处理完成了。如果这时候参数sendDone的值等于true,那么就表示需要通知系统的输入管理器,参数event所描述的键盘事件已经处理完成了,这是通过调用ViewRoot类的成员函数finishInputEvent来实现的。
接下来,我们就继续分析DecorView类的成员函数dispatchKeyEvent的实现,以便可以了解窗口的顶层视图分发键盘事件的过程。
Step 6. DecorView.dispatchKeyEvent
[java] view plaincopyprint?
public class PhoneWindow extends Window implements MenuBuilder.Callback {
......
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
......
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
final int keyCode = event.getKeyCode();
final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;
......
final Callback cb = getCallback();
final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
: super.dispatchKeyEvent(event);
if (handled) {
return true;
}
return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)
: PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);
}
......
}
......
}
public class PhoneWindow extends Window implements MenuBuilder.Callback {
......
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
......
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
final int keyCode = event.getKeyCode();
final boolean isDown = event.getAction() == KeyEvent.ACTION_DOWN;
......
final Callback cb = getCallback();
final boolean handled = cb != null && mFeatureId < 0 ? cb.dispatchKeyEvent(event)
: super.dispatchKeyEvent(event);
if (handled) {
return true;
}
return isDown ? PhoneWindow.this.onKeyDown(mFeatureId, event.getKeyCode(), event)
: PhoneWindow.this.onKeyUp(mFeatureId, event.getKeyCode(), event);
原文转自:http://blog.csdn.net/luoshengyang/article/details/8636153