@@ -135,6 +135,7 @@ class DropdownMenu<T> extends StatefulWidget {
135135 this .controller,
136136 this .initialSelection,
137137 this .onSelected,
138+ this .requestFocusOnTap,
138139 required this .dropdownMenuEntries,
139140 });
140141
@@ -228,6 +229,19 @@ class DropdownMenu<T> extends StatefulWidget {
228229 /// Defaults to null. If null, only the text field is updated.
229230 final ValueChanged <T ?>? onSelected;
230231
232+ /// Determine if the dropdown button requests focus and the on-screen virtual
233+ /// keyboard is shown in response to a touch event.
234+ ///
235+ /// By default, on mobile platforms, tapping on the text field and opening
236+ /// the menu will not cause a focus request and the virtual keyboard will not
237+ /// appear. The default behavior for desktop platforms is for the dropdown to
238+ /// take the focus.
239+ ///
240+ /// Defaults to null. Setting this field to true or false, rather than allowing
241+ /// the implementation to choose based on the platform, can be useful for
242+ /// applications that want to override the default behavior.
243+ final bool ? requestFocusOnTap;
244+
231245 /// Descriptions of the menu items in the [DropdownMenu] .
232246 ///
233247 /// This is a required parameter. It is recommended that at least one [DropdownMenuEntry]
@@ -242,7 +256,6 @@ class DropdownMenu<T> extends StatefulWidget {
242256class _DropdownMenuState <T > extends State <DropdownMenu <T >> {
243257 final GlobalKey _anchorKey = GlobalKey ();
244258 final GlobalKey _leadingKey = GlobalKey ();
245- final FocusNode _textFocusNode = FocusNode ();
246259 final MenuController _controller = MenuController ();
247260 late final TextEditingController _textEditingController;
248261 late bool _enableFilter;
@@ -288,6 +301,23 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
288301 }
289302 }
290303
304+ bool canRequestFocus () {
305+ if (widget.requestFocusOnTap != null ) {
306+ return widget.requestFocusOnTap! ;
307+ }
308+
309+ switch (Theme .of (context).platform) {
310+ case TargetPlatform .iOS:
311+ case TargetPlatform .android:
312+ case TargetPlatform .fuchsia:
313+ return false ;
314+ case TargetPlatform .macOS:
315+ case TargetPlatform .linux:
316+ case TargetPlatform .windows:
317+ return true ;
318+ }
319+ }
320+
291321 void refreshLeadingPadding () {
292322 WidgetsBinding .instance.addPostFrameCallback ((_) {
293323 setState (() {
@@ -428,7 +458,6 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
428458
429459 @override
430460 void dispose () {
431- _textEditingController.dispose ();
432461 super .dispose ();
433462 }
434463
@@ -489,13 +518,12 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
489518 builder: (BuildContext context, MenuController controller, Widget ? child) {
490519 assert (_initialMenu != null );
491520 final Widget trailingButton = Padding (
492- padding: const EdgeInsets .symmetric (horizontal : 4.0 ),
521+ padding: const EdgeInsets .all ( 4.0 ),
493522 child: IconButton (
494523 isSelected: controller.isOpen,
495524 icon: widget.trailingIcon ?? const Icon (Icons .arrow_drop_down),
496525 selectedIcon: widget.selectedTrailingIcon ?? const Icon (Icons .arrow_drop_up),
497526 onPressed: () {
498- _textFocusNode.requestFocus ();
499527 handlePressed (controller);
500528 },
501529 ),
@@ -511,7 +539,9 @@ class _DropdownMenuState<T> extends State<DropdownMenu<T>> {
511539 width: widget.width,
512540 children: < Widget > [
513541 TextField (
514- focusNode: _textFocusNode,
542+ canRequestFocus: canRequestFocus (),
543+ enableInteractiveSelection: canRequestFocus (),
544+ textAlignVertical: TextAlignVertical .center,
515545 style: effectiveTextStyle,
516546 controller: _textEditingController,
517547 onEditingComplete: () {
0 commit comments