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 yourself 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. 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. Focus.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.


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 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 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 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 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 RawKeyboard and will pass them to the focused nodes. It starts with the node with the primary focus, and will call the onKey callback for that node. If the callback returns false, indicating that it did not handle the event, the FocusManager will move to the parent of that node and call its onKey. If that onKey returns true, 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.

This example shows how a FocusNode should be managed if not using the Focus or FocusScope widgets. See the Focus widget for a similar example using Focus and FocusScope widgets.
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


FocusNode({String debugLabel, FocusOnKeyCallback onKey, bool skipTraversal: false, bool canRequestFocus: true})
Creates a focus node. [...]


ancestors Iterable<FocusNode>
An Iterable over the ancestors of this node. [...]
canRequestFocus bool
If true, this focus node may request the primary focus. [...]
@mustCallSuper, read / write
children Iterable<FocusNode>
An iterator over the children of this node.
context BuildContext
The context that was supplied to attach. [...]
debugLabel String
A debug label that is used for diagnostic output. [...]
read / write
descendants Iterable<FocusNode>
An Iterable over the hierarchy of children below this one, in depth-first order.
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. [...]
hasFocus bool
Whether this node has input focus. [...]
hasPrimaryFocus bool
Returns true if this node currently has the application-wide input focus. [...]
highlightMode FocusHighlightMode
Returns the FocusHighlightMode that is currently in effect for this node.
nearestScope FocusScopeNode
Returns the nearest enclosing scope node above this node, including this node, if it's a scope. [...]
offset Offset
Returns the global offset to the upper left corner of the attached widget's RenderObject, in logical units.
onKey FocusOnKeyCallback
Called if this focus node receives a key event while focused (i.e. when hasFocus returns true). [...]
parent FocusNode
Returns the parent node for this object. [...]
rect Rect
Returns the global rectangle of the attached widget's RenderObject, in logical units.
size Size
Returns the size of the attached widget's RenderObject, in logical units.
skipTraversal bool
If true, tells the focus traversal policy to skip over this node for purposes of the traversal algorithm. [...]
read / write
traversalChildren Iterable<FocusNode>
An iterator over the children that are allowed to be traversed by the FocusTraversalPolicy.
traversalDescendants Iterable<FocusNode>
Returns all descendants which do not have the skipTraversal and do have the canRequestFocus flag set.
hashCode int
The hash code for this object. [...]
read-only, inherited
hasListeners bool
Whether any listeners are currently registered.
@protected, read-only, inherited
runtimeType Type
A representation of the runtime type of the object.
read-only, inherited


attach(BuildContext context, {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. [...]
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node. [...]
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 and removeListener will throw after the object is disposed). [...]
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 method. [...]
previousFocus() bool
Request to move the focus to the previous focus node, by calling the FocusTraversalPolicy.previous method. [...]
requestFocus([FocusNode node]) → void
Requests the primary focus for this node, or for a supplied node, which will also give focus to its ancestors. [...]
toStringShort() String
A brief description of this object, usually just the runtimeType and the hashCode. [...]
unfocus({UnfocusDisposition disposition: UnfocusDisposition.scope}) → void
Removes the focus on this node by moving the primary focus to another node. [...]
addListener(VoidCallback listener) → void
Register a closure to be called when the object changes.
noSuchMethod(Invocation invocation) → dynamic
Invoked when a non-existent method or property is accessed. [...]
notifyListeners() → void
Call all the registered listeners.
@protected, @visibleForTesting, inherited
removeListener(VoidCallback listener) → void
Remove a previously registered closure from the list of closures that are notified when the object changes.
toDiagnosticsNode({String name, DiagnosticsTreeStyle style}) DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep.
toString({DiagnosticLevel minLevel:}) String
Returns a string representation of this object.
toStringDeep({String prefixLineOne: '', String prefixOtherLines, DiagnosticLevel minLevel: DiagnosticLevel.debug}) String
Returns a string representation of this node and its descendants.
toStringShallow({String joiner: ', ', DiagnosticLevel minLevel: DiagnosticLevel.debug}) String
Returns a one-line detailed description of the object.


operator ==(dynamic other) bool
The equality operator. [...]