DefaultTextEditingShortcuts class
A widget with the shortcuts used for the default text editing behavior.
This default behavior can be overridden by placing a Shortcuts widget lower in the widget tree than this. See the Action class for an example of remapping an Intent to a custom Action.
The Shortcuts widget usually takes precedence over system keybindings. Proceed with caution if the shortcut you wish to override is also used by the system. For example, overriding LogicalKeyboardKey.backspace could cause CJK input methods to discard more text than they should when the backspace key is pressed during text composition on iOS.
Interactions Between Shortcuts and Text Input
Shortcuts prevent text input fields from receiving their keystrokes as text input. For example, placing a Shortcuts widget in the widget tree above a text input field and creating a shortcut for LogicalKeyboardKey.keyA will prevent the field from receiving that key as text input. In other words, typing key "A" into the field will trigger the shortcut and will not insert a letter "a" into the field.
This happens because of the way that key strokes are handled in Flutter. When a keystroke is received in Flutter's engine, it first gives the framework the opportunity to handle it as a raw key event through SystemChannels.keyEvent. This is what Shortcuts listens to indirectly through its FocusNode. If it is not handled, then it will proceed to try handling it as text input through SystemChannels.textInput, which is what EditableTextState listens to through TextInputClient.
This behavior, where a shortcut prevents text input into some field, can be overridden by using another Shortcuts widget lower in the widget tree and mapping the desired key stroke(s) to DoNothingAndStopPropagationIntent. The key event will be reported as unhandled by the framework and will then be sent as text input as usual.
@override
Widget build(BuildContext context) {
// If using WidgetsApp or its descendants MaterialApp or CupertinoApp,
// then DefaultTextEditingShortcuts is already being inserted into the
// widget tree.
return const DefaultTextEditingShortcuts(
child: Center(
child: Shortcuts(
shortcuts: <ShortcutActivator, Intent>{
SingleActivator(LogicalKeyboardKey.arrowDown, alt: true): NextFocusIntent(),
SingleActivator(LogicalKeyboardKey.arrowUp, alt: true): PreviousFocusIntent(),
},
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
hintText: 'alt + down moves to the next field.',
),
),
TextField(
decoration: InputDecoration(
hintText: 'And alt + up moves to the previous.',
),
),
],
),
),
),
);
}
class IncrementCounterIntent extends Intent {}
class DecrementCounterIntent extends Intent {}
class MyWidget extends StatefulWidget {
const MyWidget({ super.key });
@override
MyWidgetState createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
int _counter = 0;
@override
Widget build(BuildContext context) {
// If using WidgetsApp or its descendants MaterialApp or CupertinoApp,
// then DefaultTextEditingShortcuts is already being inserted into the
// widget tree.
return DefaultTextEditingShortcuts(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headlineMedium,
),
Shortcuts(
shortcuts: <ShortcutActivator, Intent>{
const SingleActivator(LogicalKeyboardKey.arrowUp): IncrementCounterIntent(),
const SingleActivator(LogicalKeyboardKey.arrowDown): DecrementCounterIntent(),
},
child: Actions(
actions: <Type, Action<Intent>>{
IncrementCounterIntent: CallbackAction<IncrementCounterIntent>(
onInvoke: (IncrementCounterIntent intent) {
setState(() {
_counter++;
});
return null;
},
),
DecrementCounterIntent: CallbackAction<DecrementCounterIntent>(
onInvoke: (DecrementCounterIntent intent) {
setState(() {
_counter--;
});
return null;
},
),
},
child: const TextField(
maxLines: 2,
decoration: InputDecoration(
hintText: 'Up/down increment/decrement here.',
),
),
),
),
const TextField(
maxLines: 2,
decoration: InputDecoration(
hintText: 'Up/down behave normally here.',
),
),
],
),
),
);
}
}
See also:
- WidgetsApp, which creates a DefaultTextEditingShortcuts.
- Inheritance
-
- Object
- DiagnosticableTree
- Widget
- StatelessWidget
- DefaultTextEditingShortcuts
Constructors
- DefaultTextEditingShortcuts({Key? key, required Widget child})
-
Creates a DefaultTextEditingShortcuts widget that provides the default text editing
shortcuts on the current platform.
const
Properties
- child → Widget
-
This widget can only have one child. To lay out multiple children, let this
widget's child be a widget such as Row, Column, or Stack, which have a
children
property, and then provide the children to that widget.final - hashCode → int
-
The hash code for this object.
no setterinherited
- key → Key?
-
Controls how one widget replaces another widget in the tree.
finalinherited
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
Methods
-
build(
BuildContext context) → Widget -
Describes the part of the user interface represented by this widget.
override
-
createElement(
) → StatelessElement -
Creates a StatelessElement to manage this widget's location in the tree.
inherited
-
debugDescribeChildren(
) → List< DiagnosticsNode> -
Returns a list of DiagnosticsNode objects describing this node's
children.
inherited
-
debugFillProperties(
DiagnosticPropertiesBuilder properties) → void -
Add additional properties associated with the node.
inherited
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
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, int wrapWidth = 65}) → 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 short, textual description of this widget.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited