FocusNode class
An object that can be used by a stateful widget to obtain the keyboard focus and to handle keyboard events.
Please see the Focus and FocusScope widgets, which are utility widgets that manage their own FocusNodes and FocusScopeNodes, respectively. If they aren't appropriate, FocusNodes can be managed directly, but doing this is rare.
FocusNodes are persistent objects that form a focus tree that is a representation of the widgets in the hierarchy that are interested in focus. A focus node might need to be created if it is passed in from an ancestor of a Focus widget to control the focus of the children from the ancestor, or a widget might need to host one if the widget subsystem is not being used, or if the Focus and FocusScope widgets provide insufficient control.
FocusNodes are organized into scopes (see FocusScopeNode), which form sub-trees of nodes that restrict traversal to a group of nodes. Within a scope, the most recent nodes to have focus are remembered, and if a node is focused and then unfocused, the previous node receives focus again.
The focus node hierarchy can be traversed using the parent, children, ancestors and descendants accessors.
FocusNodes are ChangeNotifiers, so a listener can be registered to receive a notification when the focus changes. Listeners will also be notified when skipTraversal, canRequestFocus, descendantsAreFocusable, and descendantsAreTraversable properties are updated. If the Focus and FocusScope widgets are being used to manage the nodes, consider establishing an InheritedWidget dependency on them by calling Focus.of or FocusScope.of instead. FocusNode.hasFocus can also be used to establish a similar dependency, especially if all that is needed is to determine whether or not the widget is focused at build time.
To see the focus tree in the debug console, call debugDumpFocusTree. To get the focus tree as a string, call debugDescribeFocusTree.
Lifecycle
There are several actors involved in the lifecycle of a FocusNode/FocusScopeNode. They are created and disposed by their owner, attached, detached, and re-parented using a FocusAttachment by their host (which must be owned by the State of a StatefulWidget), and they are managed by the FocusManager. Different parts of the FocusNode API are intended for these different actors.
FocusNodes (and hence FocusScopeNodes) are persistent objects that form part of a focus tree that is a sparse representation of the widgets in the hierarchy that are interested in receiving keyboard events. They must be managed like other persistent state, which is typically done by a StatefulWidget that owns the node. A stateful widget that owns a focus scope node must call dispose from its State.dispose method.
Once created, a FocusNode must be attached to the widget tree via a FocusAttachment object. This attachment is created by calling attach, usually from the State.initState method. If the hosting widget is updated to have a different focus node, then the updated node needs to be attached in State.didUpdateWidget, after calling FocusAttachment.detach on the previous FocusAttachment.
Because FocusNodes form a sparse representation of the widget tree, they must be updated whenever the widget tree is rebuilt. This is done by calling FocusAttachment.reparent, usually from the State.build or State.didChangeDependencies methods of the widget that represents the focused region, so that the BuildContext assigned to the FocusScopeNode can be tracked (the context is used to obtain the RenderObject, from which the geometry of focused regions can be determined).
Creating a FocusNode each time State.build is invoked will cause the focus to be lost each time the widget is built, which is usually not desired behavior (call unfocus if losing focus is desired).
If, as is common, the hosting StatefulWidget is also the owner of the focus node, then it will also call dispose from its State.dispose (in which case the FocusAttachment.detach may be skipped, since dispose will automatically detach). If another object owns the focus node, then it must call dispose when the node is done being used.
Key Event Propagation
The FocusManager receives key events from HardwareKeyboard and will pass them to the focused nodes. It starts with the node with the primary focus, and will call the onKeyEvent callback for that node. If the callback returns KeyEventResult.ignored, indicating that it did not handle the event, the FocusManager will move to the parent of that node and call its onKeyEvent. If that onKeyEvent returns KeyEventResult.handled, then it will stop propagating the event. If it reaches the root FocusScopeNode, FocusManager.rootScope, the event is discarded.
Focus Traversal
The term traversal, sometimes called tab traversal, refers to moving the focus from one widget to the next in a particular order (also sometimes referred to as the tab order, since the TAB key is often bound to the action to move to the next widget).
To give focus to the logical next or previous widget in the UI, call the nextFocus or previousFocus methods. To give the focus to a widget in a particular direction, call the focusInDirection method.
The policy for what the next or previous widget is, or the widget in a particular direction, is determined by the FocusTraversalPolicy in force.
The ambient policy is determined by looking up the widget hierarchy for a FocusTraversalGroup widget, and obtaining the focus traversal policy from it. Different focus nodes can inherit difference policies, so part of the app can go in a predefined order (using OrderedTraversalPolicy), and part can go in reading order (using ReadingOrderTraversalPolicy), depending upon the use case.
Predefined policies include WidgetOrderTraversalPolicy, ReadingOrderTraversalPolicy, OrderedTraversalPolicy, and DirectionalFocusTraversalPolicyMixin, but custom policies can be built based upon these policies. See FocusTraversalPolicy for more information.
To create a local project with this code sample, run:
flutter create --sample=widgets.FocusNode.1 mysample
See also:
- Focus, a widget that manages a FocusNode and provides access to focus information and actions to its descendant widgets.
- FocusTraversalGroup, a widget used to group together and configure the focus traversal policy for a widget subtree.
- FocusManager, a singleton that manages the primary focus and distributes key events to focused nodes.
- FocusTraversalPolicy, a class used to determine how to move the focus to other nodes.
- Mixed in types
- Implementers
Constructors
- FocusNode({String? debugLabel, @Deprecated('Use onKeyEvent instead. ' 'This feature was deprecated after v3.18.0-2.0.pre.') FocusOnKeyCallback? onKey, FocusOnKeyEventCallback? onKeyEvent, bool skipTraversal = false, bool canRequestFocus = true, bool descendantsAreFocusable = true, bool descendantsAreTraversable = true})
- Creates a focus node.
Properties
-
ancestors
→ Iterable<
FocusNode> -
An Iterable over the ancestors of this node.
no setter
- canRequestFocus ↔ bool
-
If true, this focus node may request the primary focus.
getter/setter pair
-
children
→ Iterable<
FocusNode> -
An iterator over the children of this node.
no setter
- context → BuildContext?
-
The context that was supplied to attach.
no setter
- debugLabel ↔ String?
-
A debug label that is used for diagnostic output.
getter/setter pair
-
descendants
→ Iterable<
FocusNode> -
An Iterable over the hierarchy of children below this one, in
depth-first order.
no setter
- descendantsAreFocusable ↔ bool
-
If false, will disable focus for all of this node's descendants.
getter/setter pair
- descendantsAreTraversable ↔ bool
-
If false, tells the focus traversal policy to skip over for all of this
node's descendants for purposes of the traversal algorithm.
getter/setter pair
- enclosingScope → FocusScopeNode?
-
Returns the nearest enclosing scope node above this node, or null if the
node has not yet be added to the focus tree.
no setter
- hasFocus → bool
-
Whether this node has input focus.
no setter
- hashCode → int
-
The hash code for this object.
no setterinherited
- hasListeners → bool
-
Whether any listeners are currently registered.
no setterinherited
- hasPrimaryFocus → bool
-
Returns true if this node currently has the application-wide input focus.
no setter
- highlightMode → FocusHighlightMode
-
Returns the FocusHighlightMode that is currently in effect for this node.
no setter
- nearestScope → FocusScopeNode?
-
Returns the nearest enclosing scope node above this node, including
this node, if it's a scope.
no setter
- offset → Offset
-
Returns the global offset to the upper left corner of the attached
widget's RenderObject, in logical units.
no setter
- onKey ↔ FocusOnKeyCallback?
-
Called if this focus node receives a key event while focused (i.e. when
hasFocus returns true).
getter/setter pair
- onKeyEvent ↔ FocusOnKeyEventCallback?
-
Called if this focus node receives a key event while focused (i.e. when
hasFocus returns true).
getter/setter pair
- parent → FocusNode?
-
Returns the parent node for this object.
no setter
- rect → Rect
-
Returns the global rectangle of the attached widget's RenderObject, in
logical units.
no setter
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- size → Size
-
Returns the size of the attached widget's RenderObject, in logical
units.
no setter
- skipTraversal ↔ bool
-
If true, tells the focus traversal policy to skip over this node for
purposes of the traversal algorithm.
getter/setter pair
-
traversalChildren
→ Iterable<
FocusNode> -
An iterator over the children that are allowed to be traversed by the
FocusTraversalPolicy.
no setter
-
traversalDescendants
→ Iterable<
FocusNode> -
Returns all descendants which do not have the skipTraversal and do have
the canRequestFocus flag set.
no setter
Methods
-
addListener(
VoidCallback listener) → void -
Register a closure to be called when the object changes.
inherited
-
attach(
BuildContext? context, {FocusOnKeyEventCallback? onKeyEvent, FocusOnKeyCallback? onKey}) → FocusAttachment - Called by the host StatefulWidget to attach a FocusNode to the widget tree.
-
consumeKeyboardToken(
) → bool - Removes the keyboard token from this focus node if it has one.
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
override
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
override
-
dispose(
) → void -
Discards any resources used by the object. After this is called, the
object is not in a usable state and should be discarded (calls to
addListener will throw after the object is disposed).
override
-
focusInDirection(
TraversalDirection direction) → bool - Request to move the focus to the nearest focus node in the given direction, by calling the FocusTraversalPolicy.inDirection method.
-
nextFocus(
) → bool - Request to move the focus to the next focus node, by calling the FocusTraversalPolicy.next method.
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
notifyListeners(
) → void -
Call all the registered listeners.
inherited
-
previousFocus(
) → bool - Request to move the focus to the previous focus node, by calling the FocusTraversalPolicy.previous method.
-
removeListener(
VoidCallback listener) → void -
Remove a previously registered closure from the list of closures that are
notified when the object changes.
inherited
-
requestFocus(
[FocusNode? node]) → void -
Requests the primary focus for this node, or for a supplied
node
, which will also give focus to its ancestors. -
toDiagnosticsNode(
{String? name, DiagnosticsTreeStyle? style}) → DiagnosticsNode -
Returns a debug representation of the object that is used by debugging
tools and by DiagnosticsNode.toStringDeep.
inherited
-
toString(
{DiagnosticLevel minLevel = DiagnosticLevel.info}) → String -
A string representation of this object.
inherited
-
toStringDeep(
{String prefixLineOne = '', String? prefixOtherLines, DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a string representation of this node and its descendants.
inherited
-
toStringShallow(
{String joiner = ', ', DiagnosticLevel minLevel = DiagnosticLevel.debug}) → String -
Returns a one-line detailed description of the object.
inherited
-
toStringShort(
) → String -
A brief description of this object, usually just the runtimeType and the
hashCode.
override
-
unfocus(
{UnfocusDisposition disposition = UnfocusDisposition.scope}) → void - Removes the focus on this node by moving the primary focus to another node.
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited