Focus相关

2020-04-23  本文已影响0人  liboxiang

备注:文中忽略了部分逻辑的,该文只是为了理解focus和unfocus过程,及怎么显示键盘和收起键盘的

focus.png

EditableText

Focus相关的类都是配合EditableText使用的

///EditableTextState class
 bool get _hasFocus => widget.focusNode.hasFocus;

由上面的流程图可以知道,EditableTextState initState的时候会监听widget.focusNode,当接收到通知的时候最终会调用_openOrCloseInputConnectionIfNeeded方法。在_openOrCloseInputConnectionIfNeeded方法内会判断_hasFocus,然后调用_openInputConnection()_closeInputConnectionIfNeeded()

Focus相关

widget

两者的state的build方法中都会调用_focusAttachment.reparent();以将FocusNode和前面的node树连接起来。同时,两者的state的build方法中都使用到class _FocusMarker extends InheritedNotifier<FocusNode>
Focus和FocusScope的InheritedWidget标记。

reparent

由上面流程图可知,在EditableTextState的build方法中会调用FocusAttachment的reparent方法,将最近_FocusMarker中的FocusNode或者BuildOwner中focusManager的rootScope设置为node的parent,则将parent赋值给node._parent,并将node添加到parent的_children数组中。
由以上流程图可知,调用this.requestFocus(focusNode)方法,会将this设置为focusNode的parent。

requestFocus->_doRequestFocus

由流程图可知,对于FocusNode和FocusScopeNode,调用requestFocus方法,最终是分别调用各自的_doRequestFocus方法。_doRequestFocus方法中各自的逻辑如下:

///FocusScopeNode class
FocusNode get focusedChild {
    assert(_focusedChildren.isEmpty || _focusedChildren.last.enclosingScope == this, 'Focused child does not have the same idea of its enclosing scope as the scope does.');
    return _focusedChildren.isNotEmpty ? _focusedChildren.last : null;
  }

同时会调用_markAsDirty方法,在该方法内调node的_notify方法或者调_manager的_markNeedsUpdate

FocusManager

///当前focus的node
FocusNode get primaryFocus => _primaryFocus;
FocusNode _primaryFocus;
///请求focus,但是还没有focus的node
FocusNode _nextFocus;

由以上流程图可知,当focus的时候,会先将请求focus的node传递给_nextFocus,让后在调用node._notify()之前将_nextFocus赋值给_primaryFocus,并将_nextFocus置空。
当unfocus的时候,会将_primaryFocus和_nextFocus都置空,同时还会调用node._notify()

上一篇下一篇

猜你喜欢

热点阅读