View.onFocusedChanged()
该函数的作用是处理一些由于焦点变化所导致的其他状态变化的逻辑。
protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect){
//判断是获得了焦点还是失去了焦点。
if (gainFocus) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
}
InputMethodManager imm = InputMethodManager.peekInstance();
if (!gainFocus) {
if (isPressed()) {
//如果没有获取焦点但是当前正处于PRESSED状态,就必须清除PRESSED状态。
setPressed(false);
}
if (imm != null && mAttachInfo != null
&& mAttachInfo.mHasWindowFocus) {
//如果正在和输入法进行交互,则调用imm.focusOut(),该函数内部会隐藏输入法窗口,并断开输入法服务和当前窗口的连接。这里要注意的是,该步中是针对当前窗口正在和输入法交互,因为代码中是查询变量 mAttachInfo.mHasWindowFocus。mAttachInfo是View的内部类。mHasWindowFocus表示当前窗口是否是"前台窗口"。
imm.focusOut(this);
}
//调用onFocusLost(),见下:
onFocusLost();
} else if (imm != null && mAttachInfo != null
&& mAttachInfo.mHasWindowFocus) {
//如果视图是获得焦点,调用imm.focusIn()。该函数中,如果该视图是可编辑的,将会启动输入法,并显示输入法窗口。
imm.focusIn(this);
}
//调用invalidate(),因为在一般情况下焦点改变后,都会引起视图背景图的改变。
invalidate();
//回调mOnFocusChangeListener().onFocusChange(),应用程序可以实现该回调接口,以便进行其他操作。
if (mOnFocusChangeListener != null) {
mOnFocusChangeListener.onFocusChange(this, gainFocus);
}
if (mAttachInfo != null) {
mAttachInfo.mKeyDispatchState.reset(this);
}
}
View.onFocusLost()
protected void onFocusLost() {
resetPressedState();
}
View.resetPressedState()
private void resetPressedState() {
if ((mViewFlags & ENABLED_MASK) == DISABLED) {
return;
}
if (isPressed()) {
//清除Pressed状态
setPressed(false);
//删除长按监测
if (!mHasPerformedLongPress) {
removeLongPressCallback();
}
}
}