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

发表于:2013-04-02来源:Csdn作者:罗升阳点击数: 标签:Android
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; br

  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