Android控件TextView的实现原理分析(9)

发表于:2013-04-02来源:Csdn作者:罗升阳点击数: 标签:Android
...... public boolean dispatchKeyEvent(KeyEvent event) { // If any attached key listener a first crack at the event. //noinspection SimplifiableIfStatement ...... if (mOnKeyListener != null (mViewFlag

  ......

  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来实现的。

  注册到当前正在处理的视图的键盘事件监听器在处理完成参数event所描述的键盘事件之后,如果希望该键盘事件还能继续往下处理,那么View类的成员函数dispatchKeyEvent就会继续调用参数event所指向的一个KeyEvent对象的成员函数dispatch来处理该键盘事件。

  接下来,我们就继续分析KeyEvent类的成员函数dispatch的实现,以便可以了解键盘事件在Activity组件窗口的分发过程。

  Step 12. KeyEvent.dispatch

  [java] view plaincopyprint?

  public class KeyEvent extends InputEvent implements Parcelable {

  ......

  public final boolean dispatch(Callback receiver, DispatcherState state,

  Object target) {

  switch (mAction) {

  case ACTION_DOWN: {

  ......

  boolean res = receiver.onKeyDown(mKeyCode, this);

  ......

  return res;

  }

  case ACTION_UP:

  ......

  return receiver.onKeyUp(mKeyCode, this);

  case ACTION_MULTIPLE:

  final int count = mRepeatCount;

  final int code = mKeyCode;

  if (receiver.onKeyMultiple(code, count, this)) {

  return true;

  }

  ......

  return false;

  }

  return false;

  }

  ......

  }

  public class KeyEvent extends InputEvent implements Parcelable {

  ......

  public final boolean dispatch(Callback receiver, DispatcherState state,

  Object target) {

  switch (mAction) {

  case ACTION_DOWN: {

  ......

  boolean res = receiver.onKeyDown(mKeyCode, this);

  ......

  return res;

  }

  case ACTION_UP:

  ......

  return receiver.onKeyUp(mKeyCode, this);

  case ACTION_MULTIPLE:

  final int count = mRepeatCount;

  final int code = mKeyCode;

  if (receiver.onKeyMultiple(code, count, this)) {

  return true;

  }

  ......

  return false;

  }

  return false;

  }

  ......

  }

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

  从前面的调用过程可以知道,参数receiver指向的是一个View对象所实现的一个KeyEvent.Callback接口,这个KeyEvent.Callback接口是用来接收当前正在处理的键盘事件。

  KeyEvent类的成员变量mAction描述的的是当前正在处理的键盘事件的类型,当它的值等于ACTION_DOWN、ACTION_UP和ACTION_MULTIPLE的时候,KeyEvent类的成员函数dispatch就会分别调用参数receiver所指向的一个View对象的成员函数onKeyDown、onKeyUp和onKeyMultiple来接收当前正在处理的键盘事件。

  假设当前正在处理的键盘事件是与按键按下相关的,即KeyEvent类的成员变量mAction的值等于ACTION_DOWN,那么接下来就会调用参数receiver所指向的一个View对象的成员函数onKeyDown来接收当前正在处理的键盘事件。

  由于前面我们已经假设了当前获得焦点的是一个TextView控件,因此,参数receiver指向的实际上是一个TextView对象。TextView类重写了父类View的成员函数onKeyDown,因此,接下来KeyEvent类的成员函数dispatch就会调用TextView类的成员函数onKeyDown来接收当前正在处理的键盘事件。

原文转自:http://blog.csdn.net/luoshengyang/article/details/8636153