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