Step 10. ViewGroup.dispatchKeyEvent

  [java] view plaincopyprint?

  public abstract class ViewGroup extends View implements ViewParent, ViewManager {

  ......

  @Override

  public boolean dispatchKeyEvent(KeyEvent event) {

  if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {

  return super.dispatchKeyEvent(event);

  } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {

  return mFocused.dispatchKeyEvent(event);

  }

  return false;

  }

  ......

  }

  public abstract class ViewGroup extends View implements ViewParent, ViewManager {

  ......

  @Override

  public boolean dispatchKeyEvent(KeyEvent event) {

  if ((mPrivateFlags & (FOCUSED | HAS_BOUNDS)) == (FOCUSED | HAS_BOUNDS)) {

  return super.dispatchKeyEvent(event);

  } else if (mFocused != null && (mFocused.mPrivateFlags & HAS_BOUNDS) == HAS_BOUNDS) {

  return mFocused.dispatchKeyEvent(event);

  }

  return false;

  }

  ......

  }

  这个函数定义在文件frameworks/base/core/java/android/view/ViewGroup.java中。

  ViewGroup类的成员函数dispatchKeyEvent的实现与在前面的Step 3中所介绍的ViewGroup类的成员函数dispatchKeyEventPreIme的实现是类似的,即如果当前正在处理的视图容器能够获得焦点并且该视图容器的大小已经计算好了,那么会将参数event所描述的键盘事件分发给它的父类View的成员函数dispatchKeyEvent来处理,否则的话,如果当前正在处理的视图容器有一个焦点子视图,并且这个焦点子视图的大小已经计算好了,那么将参数event所描述的键盘事件分发给该焦点子视图的父类View的成员函数dispatchKeyEvent来处理。

  从前面的调用过程可以知道,当前正在处理的视图容器即为Activity组件窗口的顶层视图。我们假设在该顶层视图中,获得焦点的是一个TextView控件,并且这个TextView控件的大小已经计算好了,那么接下来会调用这个TextView控件的父类View的成员函数dispatchKeyEvent来处理参数event所描述的键盘事件。

  Step 11. View.dispatchKeyEvent

  [java] view plaincopyprint?

  public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {

  ......

  private OnKeyListener mOnKeyListener;

  ......

  public boolean dispatchKeyEvent(KeyEvent event) {

  // If any attached key listener a first crack at the event.

  //noinspection SimplifiableIfStatement

  ......

  if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED

  && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {

  return true;

  }

  return event.dispatch(this, mAttachInfo != null

  ? mAttachInfo.mKeyDispatchState : null, this);

  }

  ......

  }

  public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {

  ......

  private OnKeyListener mOnKeyListener;

  ......

  public boolean dispatchKeyEvent(KeyEvent event) {

  // If any attached key listener a first crack at the event.

  //noinspection SimplifiableIfStatement

  ......

  if (mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED

  && mOnKeyListener.onKey(this, event.getKeyCode(), event)) {

  return true;

  }

  return event.dispatch(this, mAttachInfo != null

  ? mAttachInfo.mKeyDispatchState : null, this);

  }

  ......

  }

  这个函数定义在文件frameworks/base/core/java/android/view/View.java中。

  当View类的成员变量mOnKeyListener的值不等于null时,它所指向的一个OnKeyListener对象描述的是注册到当前正在处理的视图的一个键盘事件监听器。在这种情况下,如果当前正在处理的视图是处于启用状态的,即它的成员变量mViewFlags的ENABLED位等于1,那么参数event所描述的键盘事件先分给该键盘事件监听器处理,这是通过调用View类的成员变量mOnKeyListener所指向的一个OnKeyListener对象的成员函数onKey来实现的。