Unverified Commit a24bfed0 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Add autofocus parameter to widgets which use Focus widget internally (#37809)

Add an autofocus parameter to widgets which use Focus widget internally, and update related docs.

This will allow developers to request that a particular widget be automatically focused when shown.
parent 5acf63d3
......@@ -160,7 +160,7 @@ class _CupertinoTextFieldSelectionGestureDetectorBuilder extends TextSelectionGe
/// Design UI conventions.
/// * [EditableText], which is the raw text editing control at the heart of a
/// [TextField].
/// * Learn how to use a [TextEditingController] in one of our [cookbook recipe]s.(https://flutter.dev/docs/cookbook/forms/text-field-changes#2-use-a-texteditingcontroller)
/// * Learn how to use a [TextEditingController] in one of our [cookbook recipes](https://flutter.dev/docs/cookbook/forms/text-field-changes#2-use-a-texteditingcontroller).
class CupertinoTextField extends StatefulWidget {
/// Creates an iOS-style text field.
///
......@@ -179,6 +179,13 @@ class CupertinoTextField extends StatefulWidget {
/// The text cursor is not shown if [showCursor] is false or if [showCursor]
/// is null (the default) and [readOnly] is true.
///
/// If specified, the [maxLength] property must be greater than zero.
///
/// The [autocorrect], [autofocus], [clearButtonMode], [dragStartBehavior],
/// [expands], [maxLengthEnforced], [obscureText], [prefixMode], [readOnly],
/// [scrollPadding], [suffixMode], and [textAlign] properties must not be
/// null.
///
/// See also:
///
/// * [minLines]
......@@ -276,9 +283,7 @@ class CupertinoTextField extends StatefulWidget {
/// If null, this widget will create its own [TextEditingController].
final TextEditingController controller;
/// Controls whether this widget has keyboard focus.
///
/// If null, this widget will create its own [FocusNode].
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
/// Controls the [BoxDecoration] of the box behind the text input.
......
......@@ -31,9 +31,9 @@ class RawMaterialButton extends StatefulWidget {
/// Create a button based on [Semantics], [Material], and [InkWell] widgets.
///
/// The [shape], [elevation], [focusElevation], [hoverElevation],
/// [highlightElevation], [disabledElevation], [padding], [constraints], and
/// [clipBehavior] arguments must not be null. Additionally, [elevation],
/// [focusElevation], [hoverElevation], [highlightElevation], and
/// [highlightElevation], [disabledElevation], [padding], [constraints],
/// [autofocus], and [clipBehavior] arguments must not be null. Additionally,
/// [elevation], [focusElevation], [hoverElevation], [highlightElevation], and
/// [disabledElevation] must be non-negative.
const RawMaterialButton({
Key key,
......@@ -56,6 +56,7 @@ class RawMaterialButton extends StatefulWidget {
this.animationDuration = kThemeChangeDuration,
this.clipBehavior = Clip.none,
this.focusNode,
this.autofocus = false,
MaterialTapTargetSize materialTapTargetSize,
this.child,
}) : materialTapTargetSize = materialTapTargetSize ?? MaterialTapTargetSize.padded,
......@@ -69,6 +70,7 @@ class RawMaterialButton extends StatefulWidget {
assert(constraints != null),
assert(animationDuration != null),
assert(clipBehavior != null),
assert(autofocus != null),
super(key: key);
/// Called when the button is tapped or otherwise activated.
......@@ -232,14 +234,12 @@ class RawMaterialButton extends StatefulWidget {
/// * [MaterialTapTargetSize], for a description of how this affects tap targets.
final MaterialTapTargetSize materialTapTargetSize;
/// An optional focus node to use for requesting focus when pressed.
///
/// If not supplied, the button will create and host its own [FocusNode].
///
/// If supplied, the given focusNode will be _hosted_ by this widget. See
/// [FocusNode] for more information on what that implies.
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;
/// {@macro flutter.widgets.Clip}
final Clip clipBehavior;
......@@ -331,6 +331,7 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
final Widget result = Focus(
focusNode: widget.focusNode,
onFocusChange: _handleFocusedChanged,
autofocus: widget.autofocus,
child: ConstrainedBox(
constraints: widget.constraints,
child: Material(
......
This diff is collapsed.
......@@ -97,6 +97,8 @@ import 'theme_data.dart';
/// * <https://material.io/design/components/buttons.html>
class FlatButton extends MaterialButton {
/// Create a simple text button.
///
/// The [autofocus] and [clipBehavior] arguments must not be null.
const FlatButton({
Key key,
@required VoidCallback onPressed,
......@@ -115,9 +117,11 @@ class FlatButton extends MaterialButton {
ShapeBorder shape,
Clip clipBehavior,
FocusNode focusNode,
bool autofocus = false,
MaterialTapTargetSize materialTapTargetSize,
@required Widget child,
}) : super(
}) : assert(autofocus != null),
super(
key: key,
onPressed: onPressed,
onHighlightChanged: onHighlightChanged,
......@@ -135,6 +139,7 @@ class FlatButton extends MaterialButton {
shape: shape,
clipBehavior: clipBehavior,
focusNode: focusNode,
autofocus: autofocus,
materialTapTargetSize: materialTapTargetSize,
child: child,
);
......@@ -164,6 +169,7 @@ class FlatButton extends MaterialButton {
ShapeBorder shape,
Clip clipBehavior,
FocusNode focusNode,
bool autofocus,
MaterialTapTargetSize materialTapTargetSize,
@required Widget icon,
@required Widget label,
......@@ -192,6 +198,7 @@ class FlatButton extends MaterialButton {
shape: buttonTheme.getShape(this),
clipBehavior: clipBehavior ?? Clip.none,
focusNode: focusNode,
autofocus: autofocus,
materialTapTargetSize: buttonTheme.getMaterialTapTargetSize(this),
animationDuration: buttonTheme.getAnimationDuration(this),
child: child,
......@@ -222,11 +229,13 @@ class _FlatButtonWithIcon extends FlatButton with MaterialButtonWithIconMixin {
ShapeBorder shape,
Clip clipBehavior,
FocusNode focusNode,
bool autofocus = false,
MaterialTapTargetSize materialTapTargetSize,
@required Widget icon,
@required Widget label,
}) : assert(icon != null),
assert(label != null),
assert(autofocus != null),
super(
key: key,
onPressed: onPressed,
......@@ -245,6 +254,7 @@ class _FlatButtonWithIcon extends FlatButton with MaterialButtonWithIconMixin {
shape: shape,
clipBehavior: clipBehavior,
focusNode: focusNode,
autofocus: autofocus,
materialTapTargetSize: materialTapTargetSize,
child: Row(
mainAxisSize: MainAxisSize.min,
......
......@@ -145,6 +145,7 @@ class FloatingActionButton extends StatelessWidget {
this.shape,
this.clipBehavior = Clip.none,
this.focusNode,
this.autofocus = false,
this.materialTapTargetSize,
this.isExtended = false,
}) : assert(elevation == null || elevation >= 0.0),
......@@ -154,15 +155,16 @@ class FloatingActionButton extends StatelessWidget {
assert(disabledElevation == null || disabledElevation >= 0.0),
assert(mini != null),
assert(isExtended != null),
assert(autofocus != null),
_sizeConstraints = mini ? _kMiniSizeConstraints : _kSizeConstraints,
super(key: key);
/// Creates a wider [StadiumBorder]-shaped floating action button with
/// an optional [icon] and a [label].
///
/// The [label] and [clipBehavior] arguments must non-null. Additionally,
/// [elevation], [highlightElevation], and [disabledElevation] (if specified)
/// must be non-negative.
/// The [label], [autofocus], and [clipBehavior] arguments must non-null.
/// Additionally, [elevation], [highlightElevation], and [disabledElevation]
/// (if specified) must be non-negative.
FloatingActionButton.extended({
Key key,
this.tooltip,
......@@ -183,6 +185,7 @@ class FloatingActionButton extends StatelessWidget {
this.materialTapTargetSize,
this.clipBehavior = Clip.none,
this.focusNode,
this.autofocus = false,
Widget icon,
@required Widget label,
}) : assert(elevation == null || elevation >= 0.0),
......@@ -191,6 +194,7 @@ class FloatingActionButton extends StatelessWidget {
assert(highlightElevation == null || highlightElevation >= 0.0),
assert(disabledElevation == null || disabledElevation >= 0.0),
assert(isExtended != null),
assert(autofocus != null),
_sizeConstraints = _kExtendedSizeConstraints,
mini = false,
child = _ChildOverflowBox(
......@@ -372,14 +376,12 @@ class FloatingActionButton extends StatelessWidget {
/// floating action buttons are scaled and faded in.
final bool isExtended;
/// An optional focus node to use for requesting focus when pressed.
///
/// If not supplied, the button will create and host its own [FocusNode].
///
/// If supplied, the given focusNode will be _hosted_ by this widget. See
/// [FocusNode] for more information on what that implies.
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;
/// Configures the minimum size of the tap target.
///
/// Defaults to [ThemeData.materialTapTargetSize].
......@@ -463,6 +465,7 @@ class FloatingActionButton extends StatelessWidget {
shape: shape,
clipBehavior: clipBehavior ?? Clip.none,
focusNode: focusNode,
autofocus: autofocus,
child: child,
);
......
......@@ -131,8 +131,8 @@ class IconButton extends StatelessWidget {
///
/// Requires one of its ancestors to be a [Material] widget.
///
/// The [iconSize], [padding], and [alignment] arguments must not be null (though
/// they each have default values).
/// The [iconSize], [padding], [autofocus], and [alignment] arguments must not
/// be null (though they each have default values).
///
/// The [icon] argument must be specified, and is typically either an [Icon]
/// or an [ImageIcon].
......@@ -150,10 +150,12 @@ class IconButton extends StatelessWidget {
this.disabledColor,
@required this.onPressed,
this.focusNode,
this.autofocus = false,
this.tooltip,
}) : assert(iconSize != null),
assert(padding != null),
assert(alignment != null),
assert(autofocus != null),
assert(icon != null),
super(key: key);
......@@ -256,14 +258,12 @@ class IconButton extends StatelessWidget {
/// If this is set to null, the button will be disabled.
final VoidCallback onPressed;
/// An optional focus node to use for requesting focus when pressed.
///
/// If not supplied, the button will create and host its own [FocusNode].
///
/// If supplied, the given focusNode will be _hosted_ by this widget. See
/// [FocusNode] for more information on what that implies.
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;
/// Text that describes the action that will occur when the button is pressed.
///
/// This text is displayed when the user long-presses on the button and is
......@@ -312,6 +312,7 @@ class IconButton extends StatelessWidget {
enabled: onPressed != null,
child: Focus(
focusNode: focusNode,
autofocus: autofocus,
child: InkResponse(
onTap: onPressed,
child: result,
......
......@@ -43,6 +43,11 @@ class MaterialButton extends StatelessWidget {
/// Rather than creating a material button directly, consider using
/// [FlatButton] or [RaisedButton]. To create a custom Material button
/// consider using [RawMaterialButton].
///
/// The [autofocus] and [clipBehavior] arguments must not be null.
/// Additionally, [elevation], [hoverElevation], [focusElevation],
/// [highlightElevation], and [disabledElevation] must be non-negative, if
/// specified.
const MaterialButton({
Key key,
@required this.onPressed,
......@@ -66,12 +71,19 @@ class MaterialButton extends StatelessWidget {
this.shape,
this.clipBehavior = Clip.none,
this.focusNode,
this.autofocus = false,
this.materialTapTargetSize,
this.animationDuration,
this.minWidth,
this.height,
this.child,
}) : super(key: key);
}) : assert(autofocus != null),
assert(elevation == null || elevation >= 0.0),
assert(focusElevation == null || focusElevation >= 0.0),
assert(hoverElevation == null || hoverElevation >= 0.0),
assert(highlightElevation == null || highlightElevation >= 0.0),
assert(disabledElevation == null || disabledElevation >= 0.0),
super(key: key);
/// The callback that is called when the button is tapped or otherwise activated.
///
......@@ -296,14 +308,12 @@ class MaterialButton extends StatelessWidget {
/// {@macro flutter.widgets.Clip}
final Clip clipBehavior;
/// An optional focus node to use for requesting focus when pressed.
///
/// If not supplied, the button will create and host its own [FocusNode].
///
/// If supplied, the given focusNode will be _hosted_ by this widget. See
/// [FocusNode] for more information on what that implies.
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;
/// Defines the duration of animated changes for [shape] and [elevation].
///
/// The default value is [kThemeChangeDuration].
......
......@@ -57,7 +57,7 @@ class OutlineButton extends MaterialButton {
/// Create an outline button.
///
/// The [highlightElevation] argument must be null or a positive value
/// and the [clipBehavior] argument must not be null.
/// and the [autofocus] and [clipBehavior] arguments must not be null.
const OutlineButton({
Key key,
@required VoidCallback onPressed,
......@@ -77,8 +77,10 @@ class OutlineButton extends MaterialButton {
ShapeBorder shape,
Clip clipBehavior,
FocusNode focusNode,
bool autofocus = false,
Widget child,
}) : assert(highlightElevation == null || highlightElevation >= 0.0),
assert(autofocus != null),
super(
key: key,
onPressed: onPressed,
......@@ -95,6 +97,7 @@ class OutlineButton extends MaterialButton {
shape: shape,
clipBehavior: clipBehavior,
focusNode: focusNode,
autofocus: autofocus,
child: child,
);
......@@ -105,7 +108,7 @@ class OutlineButton extends MaterialButton {
/// at the start, and 16 at the end, with an 8 pixel gap in between.
///
/// The [highlightElevation] argument must be null or a positive value. The
/// [icon], [label], and [clipBehavior] arguments must not be null.
/// [icon], [label], [autofocus], and [clipBehavior] arguments must not be null.
factory OutlineButton.icon({
Key key,
@required VoidCallback onPressed,
......@@ -125,6 +128,7 @@ class OutlineButton extends MaterialButton {
ShapeBorder shape,
Clip clipBehavior,
FocusNode focusNode,
bool autofocus,
@required Widget icon,
@required Widget label,
}) = _OutlineButtonWithIcon;
......@@ -218,9 +222,11 @@ class _OutlineButtonWithIcon extends OutlineButton with MaterialButtonWithIconMi
ShapeBorder shape,
Clip clipBehavior,
FocusNode focusNode,
bool autofocus = false,
@required Widget icon,
@required Widget label,
}) : assert(highlightElevation == null || highlightElevation >= 0.0),
assert(autofocus != null),
assert(icon != null),
assert(label != null),
super(
......@@ -242,6 +248,7 @@ class _OutlineButtonWithIcon extends OutlineButton with MaterialButtonWithIconMi
shape: shape,
clipBehavior: clipBehavior,
focusNode: focusNode,
autofocus: autofocus,
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
......@@ -274,9 +281,11 @@ class _OutlineButton extends StatefulWidget {
this.shape,
this.clipBehavior,
this.focusNode,
this.autofocus = false,
this.child,
}) : assert(highlightElevation != null && highlightElevation >= 0.0),
assert(highlightedBorderColor != null),
assert(autofocus != null),
super(key: key);
final VoidCallback onPressed;
......@@ -297,6 +306,7 @@ class _OutlineButton extends StatefulWidget {
final ShapeBorder shape;
final Clip clipBehavior;
final FocusNode focusNode;
final bool autofocus;
final Widget child;
bool get enabled => onPressed != null;
......
......@@ -101,9 +101,10 @@ import 'theme_data.dart';
class RaisedButton extends MaterialButton {
/// Create a filled button.
///
/// The [elevation], [highlightElevation], [disabledElevation], and
/// [clipBehavior] arguments must not be null. Additionally, [elevation],
/// [highlightElevation], and [disabledElevation] must be non-negative.
/// The [autofocus] and [clipBehavior] arguments must not be null.
/// Additionally, [elevation], [hoverElevation], [focusElevation],
/// [highlightElevation], and [disabledElevation] must be non-negative, if
/// specified.
const RaisedButton({
Key key,
@required VoidCallback onPressed,
......@@ -127,10 +128,12 @@ class RaisedButton extends MaterialButton {
ShapeBorder shape,
Clip clipBehavior,
FocusNode focusNode,
bool autofocus = false,
MaterialTapTargetSize materialTapTargetSize,
Duration animationDuration,
Widget child,
}) : assert(elevation == null || elevation >= 0.0),
}) : assert(autofocus != null),
assert(elevation == null || elevation >= 0.0),
assert(focusElevation == null || focusElevation >= 0.0),
assert(hoverElevation == null || hoverElevation >= 0.0),
assert(highlightElevation == null || highlightElevation >= 0.0),
......@@ -158,6 +161,7 @@ class RaisedButton extends MaterialButton {
shape: shape,
clipBehavior: clipBehavior,
focusNode: focusNode,
autofocus: autofocus,
materialTapTargetSize: materialTapTargetSize,
animationDuration: animationDuration,
child: child,
......@@ -191,6 +195,7 @@ class RaisedButton extends MaterialButton {
ShapeBorder shape,
Clip clipBehavior,
FocusNode focusNode,
bool autofocus,
MaterialTapTargetSize materialTapTargetSize,
Duration animationDuration,
@required Widget icon,
......@@ -220,6 +225,7 @@ class RaisedButton extends MaterialButton {
constraints: buttonTheme.getConstraints(this),
shape: buttonTheme.getShape(this),
focusNode: focusNode,
autofocus: autofocus,
animationDuration: buttonTheme.getAnimationDuration(this),
materialTapTargetSize: buttonTheme.getMaterialTapTargetSize(this),
child: child,
......@@ -262,6 +268,7 @@ class _RaisedButtonWithIcon extends RaisedButton with MaterialButtonWithIconMixi
ShapeBorder shape,
Clip clipBehavior = Clip.none,
FocusNode focusNode,
bool autofocus = false,
MaterialTapTargetSize materialTapTargetSize,
Duration animationDuration,
@required Widget icon,
......@@ -271,6 +278,7 @@ class _RaisedButtonWithIcon extends RaisedButton with MaterialButtonWithIconMixi
assert(disabledElevation == null || disabledElevation >= 0.0),
assert(icon != null),
assert(label != null),
assert(autofocus != null),
super(
key: key,
onPressed: onPressed,
......@@ -291,6 +299,7 @@ class _RaisedButtonWithIcon extends RaisedButton with MaterialButtonWithIconMixi
shape: shape,
clipBehavior: clipBehavior,
focusNode: focusNode,
autofocus: autofocus,
materialTapTargetSize: materialTapTargetSize,
animationDuration: animationDuration,
child: Row(
......
......@@ -184,7 +184,10 @@ class SelectableText extends StatefulWidget {
/// If the [style] argument is null, the text will use the style from the
/// closest enclosing [DefaultTextStyle].
///
/// The [data] parameter must not be null.
/// The [showCursor], [autofocus], [dragStartBehavior], and [data] parameters
/// must not be null. If specified, the [maxLines] argument must be greater
/// than zero.
const SelectableText(
this.data, {
Key key,
......@@ -225,6 +228,8 @@ class SelectableText extends StatefulWidget {
///
/// The [textSpan] parameter must not be null and only contain [TextSpan] in
/// [textSpan.children]. Other type of [InlineSpan] is not allowed.
///
/// The [autofocus] and [dragStartBehavior] arguments must not be null.
const SelectableText.rich(
this.textSpan, {
Key key,
......
......@@ -679,13 +679,7 @@ class _ToggleButton extends StatelessWidget {
/// The splash color for the button's [InkWell].
final Color splashColor;
/// A leaf node in the focus tree for this button.
///
/// Focus is used to determine which widget should be affected by keyboard
/// events. The focus tree keeps track of which widget is currently focused
/// on by the user.
///
/// See [FocusNode] for more information about how focus nodes are used.
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
/// Called when the button is tapped or otherwise activated.
......
......@@ -339,9 +339,12 @@ class EditableText extends StatefulWidget {
/// The text cursor is not shown if [showCursor] is false or if [showCursor]
/// is null (the default) and [readOnly] is true.
///
/// The [controller], [focusNode], [style], [cursorColor], [backgroundCursorColor],
/// [textAlign], [dragStartBehavior], [rendererIgnoresPointer] and [readOnly]
/// arguments must not be null.
/// The [controller], [focusNode], [obscureText], [autocorrect], [autofocus],
/// [showSelectionHandles], [enableInteractiveSelection], [forceLine],
/// [style], [cursorColor], [cursorOpacityAnimates],[backgroundCursorColor],
/// [paintCursorAboveText], [textAlign], [dragStartBehavior], [scrollPadding],
/// [dragStartBehavior], [toolbarOptions], [rendererIgnoresPointer], and
/// [readOnly] arguments must not be null.
EditableText({
Key key,
@required this.controller,
......
......@@ -137,7 +137,7 @@ class Focus extends StatefulWidget {
///
/// The [child] argument is required and must not be null.
///
/// The [autofocus] argument must not be null.
/// The [autofocus] and [skipTraversal] arguments must not be null.
const Focus({
Key key,
@required this.child,
......@@ -190,24 +190,33 @@ class Focus extends StatefulWidget {
/// focus.
final ValueChanged<bool> onFocusChange;
/// {@template flutter.widgets.Focus.autofocus}
/// True if this widget will be selected as the initial focus when no other
/// node in its scope is currently focused.
///
/// Ideally, there is only one [Focus] with autofocus set in each
/// [FocusScope]. If there is more than one [Focus] with autofocus set, then
/// the first one added to the tree will get focus.
/// Ideally, there is only one widget with autofocus set in each [FocusScope].
/// If there is more than one widget with autofocus set, then the first one
/// added to the tree will get focus.
///
/// Must not be null. Defaults to false.
/// {@endtemplate}
final bool autofocus;
/// An optional focus node to use as the focus node for this [Focus] widget.
/// {@template flutter.widgets.Focus.focusNode}
/// An optional focus node to use as the focus node for this widget.
///
/// If one is not supplied, then one will be allocated and owned by this
/// widget.
/// If one is not supplied, then one will be automatically allocated, owned,
/// and managed by this widget. The widget will be focusable even if a
/// [focusNode] is not supplied. If supplied, the given `focusNode` will be
/// _hosted_ by this widget, but not owned. See [FocusNode] for more
/// information on what being hosted and/or owned implies.
///
/// Supplying a focus node is sometimes useful if an ancestor to this widget
/// wants to control when this widget has the focus. The owner will be
/// responsible for calling [FocusNode.dispose] on the focus node when it is
/// done with it, but this [Focus] widget will attach/detach and reparent the
/// node when needed.
/// done with it, but this widget will attach/detach and reparent the node
/// when needed.
/// {@endtemplate}
final FocusNode focusNode;
/// Sets the [FocusNode.skipTraversal] flag on the focus node so that it won't
......
......@@ -31,18 +31,27 @@ class RawKeyboardListener extends StatefulWidget {
///
/// For text entry, consider using a [EditableText], which integrates with
/// on-screen keyboards and input method editors (IMEs).
///
/// The [focusNode] and [child] arguments are required and must not be null.
///
/// The [autofocus] argument must not be null.
const RawKeyboardListener({
Key key,
@required this.focusNode,
@required this.onKey,
this.autofocus = false,
this.onKey,
@required this.child,
}) : assert(focusNode != null),
assert(autofocus != null),
assert(child != null),
super(key: key);
/// Controls whether this widget has keyboard focus.
/// {@macro flutter.widgets.Focus.focusNode}
final FocusNode focusNode;
/// {@macro flutter.widgets.Focus.autofocus}
final bool autofocus;
/// Called whenever this widget receives a raw keyboard event.
final ValueChanged<RawKeyEvent> onKey;
......@@ -113,5 +122,11 @@ class _RawKeyboardListenerState extends State<RawKeyboardListener> {
}
@override
Widget build(BuildContext context) => Focus(focusNode: widget.focusNode, child: widget.child);
Widget build(BuildContext context) {
return Focus(
focusNode: widget.focusNode,
autofocus: widget.autofocus,
child: widget.child,
);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment