From 7795dac1b66196811b3bc9b3b60c238ad9458fb3 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Wed, 13 May 2026 16:20:23 -0700 Subject: [PATCH 1/7] Use constraints from LayoutBuilder to determine max width --- .../material_ui/lib/src/search_anchor.dart | 209 +++++++++--------- 1 file changed, 106 insertions(+), 103 deletions(-) diff --git a/packages/material_ui/lib/src/search_anchor.dart b/packages/material_ui/lib/src/search_anchor.dart index c08eccafa7e4..077713a42ea5 100644 --- a/packages/material_ui/lib/src/search_anchor.dart +++ b/packages/material_ui/lib/src/search_anchor.dart @@ -869,7 +869,6 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> { showFullScreenView: showFullScreenView, animation: curvedAnimation!, topPadding: topPadding, - viewMaxWidth: _rectTween.end!.width, viewRect: viewRect, viewBuilder: viewBuilder, searchController: searchController, @@ -916,7 +915,6 @@ class _ViewContent extends StatefulWidget { required this.showFullScreenView, required this.topPadding, required this.animation, - required this.viewMaxWidth, required this.viewRect, required this.searchController, required this.suggestionsBuilder, @@ -949,7 +947,6 @@ class _ViewContent extends StatefulWidget { final bool showFullScreenView; final double topPadding; final Animation animation; - final double viewMaxWidth; final Rect viewRect; final SearchController searchController; final SuggestionsBuilder suggestionsBuilder; @@ -1138,114 +1135,120 @@ class _ViewContentState extends State<_ViewContent> { child: const Divider(height: 1), ); - return Align( - alignment: Alignment.topLeft, - child: Transform.translate( - offset: _viewRect.topLeft, - child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: minWidth, - maxWidth: _viewRect.width, - minHeight: minHeight, - maxHeight: _viewRect.height, - ), - child: Padding( - padding: widget.showFullScreenView - ? EdgeInsets.zero - : (effectivePadding ?? EdgeInsets.zero), - child: Material( - clipBehavior: Clip.antiAlias, - shape: effectiveShape, - color: effectiveBackgroundColor, - surfaceTintColor: effectiveSurfaceTint, - elevation: effectiveElevation, - child: OverflowBox( - alignment: Alignment.topLeft, - maxWidth: math.min(widget.viewMaxWidth, _screenSize!.width), - minWidth: 0, - fit: OverflowBoxFit.deferToChild, - child: FadeTransition( - opacity: viewIconsFadeCurve, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Padding( - padding: EdgeInsets.only(top: widget.topPadding), - child: SafeArea( - top: false, - bottom: false, - child: SearchBar( - autoFocus: true, - constraints: - headerConstraints ?? - (widget.showFullScreenView - ? BoxConstraints( - minHeight: _SearchViewDefaultsM3.fullScreenBarHeight, - ) - : null), - padding: WidgetStatePropertyAll( - effectiveBarPadding, - ), - leading: widget.viewLeading ?? defaultLeading, - trailing: widget.viewTrailing ?? defaultTrailing, - hintText: widget.viewHintText, - backgroundColor: const MaterialStatePropertyAll( - Colors.transparent, + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return Align( + alignment: Alignment.topLeft, + child: Transform.translate( + offset: _viewRect.topLeft, + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: minWidth, + maxWidth: _viewRect.width, + minHeight: minHeight, + maxHeight: _viewRect.height, + ), + child: Padding( + padding: widget.showFullScreenView + ? EdgeInsets.zero + : (effectivePadding ?? EdgeInsets.zero), + child: Material( + clipBehavior: Clip.antiAlias, + shape: effectiveShape, + color: effectiveBackgroundColor, + surfaceTintColor: effectiveSurfaceTint, + elevation: effectiveElevation, + child: OverflowBox( + alignment: Alignment.topLeft, + maxWidth: math.min(constraints.maxWidth, _screenSize!.width), + minWidth: 0, + fit: OverflowBoxFit.deferToChild, + child: FadeTransition( + opacity: viewIconsFadeCurve, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: EdgeInsets.only(top: widget.topPadding), + child: SafeArea( + top: false, + bottom: false, + child: SearchBar( + autoFocus: true, + constraints: + headerConstraints ?? + (widget.showFullScreenView + ? BoxConstraints( + minHeight: _SearchViewDefaultsM3.fullScreenBarHeight, + ) + : null), + padding: WidgetStatePropertyAll( + effectiveBarPadding, + ), + leading: widget.viewLeading ?? defaultLeading, + trailing: widget.viewTrailing ?? defaultTrailing, + hintText: widget.viewHintText, + backgroundColor: const MaterialStatePropertyAll( + Colors.transparent, + ), + overlayColor: const MaterialStatePropertyAll( + Colors.transparent, + ), + elevation: const MaterialStatePropertyAll(0.0), + textStyle: MaterialStatePropertyAll(effectiveTextStyle), + hintStyle: MaterialStatePropertyAll(effectiveHintStyle), + controller: _controller, + onChanged: (String value) { + widget.viewOnChanged?.call(value); + updateSuggestions(); + }, + onSubmitted: widget.viewOnSubmitted, + textCapitalization: widget.textCapitalization, + textInputAction: widget.textInputAction, + keyboardType: widget.keyboardType, + smartDashesType: widget.smartDashesType, + smartQuotesType: widget.smartQuotesType, + ), ), - overlayColor: const MaterialStatePropertyAll(Colors.transparent), - elevation: const MaterialStatePropertyAll(0.0), - textStyle: MaterialStatePropertyAll(effectiveTextStyle), - hintStyle: MaterialStatePropertyAll(effectiveHintStyle), - controller: _controller, - onChanged: (String value) { - widget.viewOnChanged?.call(value); - updateSuggestions(); - }, - onSubmitted: widget.viewOnSubmitted, - textCapitalization: widget.textCapitalization, - textInputAction: widget.textInputAction, - keyboardType: widget.keyboardType, - smartDashesType: widget.smartDashesType, - smartQuotesType: widget.smartQuotesType, ), - ), + if (!effectiveShrinkWrap || + minHeight > 0 || + widget.showFullScreenView || + result.isNotEmpty) ...[ + FadeTransition(opacity: viewDividerFadeCurve, child: viewDivider), + Flexible( + fit: (effectiveShrinkWrap && !widget.showFullScreenView) + ? FlexFit.loose + : FlexFit.tight, + child: FadeTransition( + opacity: viewListFadeOnIntervalCurve, + child: widget.viewBuilder == null + ? MediaQuery.removePadding( + context: context, + removeTop: true, + child: ListView( + padding: EdgeInsets.only( + bottom: MediaQuery.viewInsetsOf(context).bottom, + ), + shrinkWrap: effectiveShrinkWrap, + children: result.toList(), + ), + ) + : widget.viewBuilder!(result), + ), + ), + ], + ], ), - if (!effectiveShrinkWrap || - minHeight > 0 || - widget.showFullScreenView || - result.isNotEmpty) ...[ - FadeTransition(opacity: viewDividerFadeCurve, child: viewDivider), - Flexible( - fit: (effectiveShrinkWrap && !widget.showFullScreenView) - ? FlexFit.loose - : FlexFit.tight, - child: FadeTransition( - opacity: viewListFadeOnIntervalCurve, - child: widget.viewBuilder == null - ? MediaQuery.removePadding( - context: context, - removeTop: true, - child: ListView( - padding: EdgeInsets.only( - bottom: MediaQuery.viewInsetsOf(context).bottom, - ), - shrinkWrap: effectiveShrinkWrap, - children: result.toList(), - ), - ) - : widget.viewBuilder!(result), - ), - ), - ], - ], + ), ), ), ), ), ), - ), - ), + ); + }, ); } } From cb2985a4df3d1337c24f124d27200fc693486194 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Wed, 13 May 2026 16:22:38 -0700 Subject: [PATCH 2/7] Add regression test --- .../material_ui/test/search_anchor_test.dart | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/packages/material_ui/test/search_anchor_test.dart b/packages/material_ui/test/search_anchor_test.dart index 675a4e93950f..273edb806f5e 100644 --- a/packages/material_ui/test/search_anchor_test.dart +++ b/packages/material_ui/test/search_anchor_test.dart @@ -3533,6 +3533,8 @@ void main() { await tester.pump(); expect(focusNode.hasPrimaryFocus, isTrue); + await tester.tapAt(const Offset(50, 50)); + await tester.pump(); await tester.tapAt(const Offset(50, 50)); await tester.pump(); @@ -4380,6 +4382,60 @@ void main() { await tester.pump(); expect(find.text('X'), findsOne); }); + + // Regression test for https://github.com/flutter/flutter/issues/186154. + testWidgets('SearchAnchor full-screen view expands to fit screen when rotated', ( + WidgetTester tester, + ) async { + addTearDown(tester.view.reset); + + // Start in portrait mode. + const portraitModeWidth = 360.0; + const portraitModeHeight = 800.0; + tester.view.physicalSize = const Size(portraitModeWidth, portraitModeHeight); + tester.view.devicePixelRatio = 1.0; + + await tester.pumpWidget( + MaterialApp( + home: Center( + child: SearchAnchor( + isFullScreen: true, + builder: (BuildContext context, SearchController controller) { + return IconButton( + icon: const Icon(Icons.search), + onPressed: () { + controller.openView(); + }, + ); + }, + suggestionsBuilder: (BuildContext context, SearchController controller) { + return []; + }, + ), + ), + ), + ); + + // Open search view. + await tester.tap(find.byIcon(Icons.search)); + await tester.pumpAndSettle(); + + // Verify starting sizes match portrait mode. + final Size startingSize = getSearchViewSize(tester); + expect(startingSize.width, portraitModeWidth); + expect(startingSize.height, portraitModeHeight); + + // Rotate to landscape mode. + const landscapeModeWidth = portraitModeHeight; + const landscapeModeHeight = portraitModeWidth; + tester.view.physicalSize = const Size(landscapeModeWidth, landscapeModeHeight); + await tester.pumpAndSettle(); + + // Verify the view expands to match landscape mode. + final Size rotatedSize = getSearchViewSize(tester); + expect(rotatedSize.width, landscapeModeWidth); + expect(rotatedSize.height, landscapeModeHeight); + }); } Future checkSearchBarDefaults( @@ -4480,3 +4536,9 @@ Material getSearchViewMaterial(WidgetTester tester) { find.descendant(of: findViewContent(), matching: find.byType(Material)).first, ); } + +Size getSearchViewSize(WidgetTester tester) { + return tester.getSize( + find.descendant(of: findViewContent(), matching: find.byType(ConstrainedBox)).first, + ); +} From ed913e7913de06a9d3f04e40c94695215c977b54 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Fri, 15 May 2026 10:37:25 -0700 Subject: [PATCH 3/7] Use screen size if showFullScreenView is true --- .../material_ui/lib/src/search_anchor.dart | 211 +++++++++--------- 1 file changed, 105 insertions(+), 106 deletions(-) diff --git a/packages/material_ui/lib/src/search_anchor.dart b/packages/material_ui/lib/src/search_anchor.dart index 077713a42ea5..b6c447c3e4ce 100644 --- a/packages/material_ui/lib/src/search_anchor.dart +++ b/packages/material_ui/lib/src/search_anchor.dart @@ -869,6 +869,7 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> { showFullScreenView: showFullScreenView, animation: curvedAnimation!, topPadding: topPadding, + viewMaxWidth: _rectTween.end!.width, viewRect: viewRect, viewBuilder: viewBuilder, searchController: searchController, @@ -915,6 +916,7 @@ class _ViewContent extends StatefulWidget { required this.showFullScreenView, required this.topPadding, required this.animation, + required this.viewMaxWidth, required this.viewRect, required this.searchController, required this.suggestionsBuilder, @@ -947,6 +949,7 @@ class _ViewContent extends StatefulWidget { final bool showFullScreenView; final double topPadding; final Animation animation; + final double viewMaxWidth; final Rect viewRect; final SearchController searchController; final SuggestionsBuilder suggestionsBuilder; @@ -1135,120 +1138,116 @@ class _ViewContentState extends State<_ViewContent> { child: const Divider(height: 1), ); - return LayoutBuilder( - builder: (BuildContext context, BoxConstraints constraints) { - return Align( - alignment: Alignment.topLeft, - child: Transform.translate( - offset: _viewRect.topLeft, - child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: minWidth, - maxWidth: _viewRect.width, - minHeight: minHeight, - maxHeight: _viewRect.height, - ), - child: Padding( - padding: widget.showFullScreenView - ? EdgeInsets.zero - : (effectivePadding ?? EdgeInsets.zero), - child: Material( - clipBehavior: Clip.antiAlias, - shape: effectiveShape, - color: effectiveBackgroundColor, - surfaceTintColor: effectiveSurfaceTint, - elevation: effectiveElevation, - child: OverflowBox( - alignment: Alignment.topLeft, - maxWidth: math.min(constraints.maxWidth, _screenSize!.width), - minWidth: 0, - fit: OverflowBoxFit.deferToChild, - child: FadeTransition( - opacity: viewIconsFadeCurve, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Padding( - padding: EdgeInsets.only(top: widget.topPadding), - child: SafeArea( - top: false, - bottom: false, - child: SearchBar( - autoFocus: true, - constraints: - headerConstraints ?? - (widget.showFullScreenView - ? BoxConstraints( - minHeight: _SearchViewDefaultsM3.fullScreenBarHeight, - ) - : null), - padding: WidgetStatePropertyAll( - effectiveBarPadding, - ), - leading: widget.viewLeading ?? defaultLeading, - trailing: widget.viewTrailing ?? defaultTrailing, - hintText: widget.viewHintText, - backgroundColor: const MaterialStatePropertyAll( - Colors.transparent, - ), - overlayColor: const MaterialStatePropertyAll( - Colors.transparent, - ), - elevation: const MaterialStatePropertyAll(0.0), - textStyle: MaterialStatePropertyAll(effectiveTextStyle), - hintStyle: MaterialStatePropertyAll(effectiveHintStyle), - controller: _controller, - onChanged: (String value) { - widget.viewOnChanged?.call(value); - updateSuggestions(); - }, - onSubmitted: widget.viewOnSubmitted, - textCapitalization: widget.textCapitalization, - textInputAction: widget.textInputAction, - keyboardType: widget.keyboardType, - smartDashesType: widget.smartDashesType, - smartQuotesType: widget.smartQuotesType, - ), - ), - ), - if (!effectiveShrinkWrap || - minHeight > 0 || - widget.showFullScreenView || - result.isNotEmpty) ...[ - FadeTransition(opacity: viewDividerFadeCurve, child: viewDivider), - Flexible( - fit: (effectiveShrinkWrap && !widget.showFullScreenView) - ? FlexFit.loose - : FlexFit.tight, - child: FadeTransition( - opacity: viewListFadeOnIntervalCurve, - child: widget.viewBuilder == null - ? MediaQuery.removePadding( - context: context, - removeTop: true, - child: ListView( - padding: EdgeInsets.only( - bottom: MediaQuery.viewInsetsOf(context).bottom, - ), - shrinkWrap: effectiveShrinkWrap, - children: result.toList(), - ), + return Align( + alignment: Alignment.topLeft, + child: Transform.translate( + offset: _viewRect.topLeft, + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: minWidth, + maxWidth: _viewRect.width, + minHeight: minHeight, + maxHeight: _viewRect.height, + ), + child: Padding( + padding: widget.showFullScreenView + ? EdgeInsets.zero + : (effectivePadding ?? EdgeInsets.zero), + child: Material( + clipBehavior: Clip.antiAlias, + shape: effectiveShape, + color: effectiveBackgroundColor, + surfaceTintColor: effectiveSurfaceTint, + elevation: effectiveElevation, + child: OverflowBox( + alignment: Alignment.topLeft, + maxWidth: widget.showFullScreenView + ? _screenSize!.width + : math.min(widget.viewMaxWidth, _screenSize!.width), + minWidth: 0, + fit: OverflowBoxFit.deferToChild, + child: FadeTransition( + opacity: viewIconsFadeCurve, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: EdgeInsets.only(top: widget.topPadding), + child: SafeArea( + top: false, + bottom: false, + child: SearchBar( + autoFocus: true, + constraints: + headerConstraints ?? + (widget.showFullScreenView + ? BoxConstraints( + minHeight: _SearchViewDefaultsM3.fullScreenBarHeight, ) - : widget.viewBuilder!(result), - ), + : null), + padding: WidgetStatePropertyAll( + effectiveBarPadding, + ), + leading: widget.viewLeading ?? defaultLeading, + trailing: widget.viewTrailing ?? defaultTrailing, + hintText: widget.viewHintText, + backgroundColor: const MaterialStatePropertyAll( + Colors.transparent, ), - ], - ], + overlayColor: const MaterialStatePropertyAll(Colors.transparent), + elevation: const MaterialStatePropertyAll(0.0), + textStyle: MaterialStatePropertyAll(effectiveTextStyle), + hintStyle: MaterialStatePropertyAll(effectiveHintStyle), + controller: _controller, + onChanged: (String value) { + widget.viewOnChanged?.call(value); + updateSuggestions(); + }, + onSubmitted: widget.viewOnSubmitted, + textCapitalization: widget.textCapitalization, + textInputAction: widget.textInputAction, + keyboardType: widget.keyboardType, + smartDashesType: widget.smartDashesType, + smartQuotesType: widget.smartQuotesType, + ), + ), ), - ), + if (!effectiveShrinkWrap || + minHeight > 0 || + widget.showFullScreenView || + result.isNotEmpty) ...[ + FadeTransition(opacity: viewDividerFadeCurve, child: viewDivider), + Flexible( + fit: (effectiveShrinkWrap && !widget.showFullScreenView) + ? FlexFit.loose + : FlexFit.tight, + child: FadeTransition( + opacity: viewListFadeOnIntervalCurve, + child: widget.viewBuilder == null + ? MediaQuery.removePadding( + context: context, + removeTop: true, + child: ListView( + padding: EdgeInsets.only( + bottom: MediaQuery.viewInsetsOf(context).bottom, + ), + shrinkWrap: effectiveShrinkWrap, + children: result.toList(), + ), + ) + : widget.viewBuilder!(result), + ), + ), + ], + ], ), ), ), ), ), - ); - }, + ), + ), ); } } From 12e5795ef5087cc3ccfa532c478c9750a30ba924 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Mon, 18 May 2026 14:39:13 -0700 Subject: [PATCH 4/7] Height resizes correctly as well --- .../material_ui/lib/src/search_anchor.dart | 212 +++++++++--------- .../material_ui/test/search_anchor_test.dart | 68 ++++++ 2 files changed, 178 insertions(+), 102 deletions(-) diff --git a/packages/material_ui/lib/src/search_anchor.dart b/packages/material_ui/lib/src/search_anchor.dart index b6c447c3e4ce..95e7dc175806 100644 --- a/packages/material_ui/lib/src/search_anchor.dart +++ b/packages/material_ui/lib/src/search_anchor.dart @@ -1138,116 +1138,124 @@ class _ViewContentState extends State<_ViewContent> { child: const Divider(height: 1), ); - return Align( - alignment: Alignment.topLeft, - child: Transform.translate( - offset: _viewRect.topLeft, - child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: minWidth, - maxWidth: _viewRect.width, - minHeight: minHeight, - maxHeight: _viewRect.height, - ), - child: Padding( - padding: widget.showFullScreenView - ? EdgeInsets.zero - : (effectivePadding ?? EdgeInsets.zero), - child: Material( - clipBehavior: Clip.antiAlias, - shape: effectiveShape, - color: effectiveBackgroundColor, - surfaceTintColor: effectiveSurfaceTint, - elevation: effectiveElevation, - child: OverflowBox( - alignment: Alignment.topLeft, - maxWidth: widget.showFullScreenView - ? _screenSize!.width - : math.min(widget.viewMaxWidth, _screenSize!.width), - minWidth: 0, - fit: OverflowBoxFit.deferToChild, - child: FadeTransition( - opacity: viewIconsFadeCurve, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Padding( - padding: EdgeInsets.only(top: widget.topPadding), - child: SafeArea( - top: false, - bottom: false, - child: SearchBar( - autoFocus: true, - constraints: - headerConstraints ?? - (widget.showFullScreenView - ? BoxConstraints( - minHeight: _SearchViewDefaultsM3.fullScreenBarHeight, - ) - : null), - padding: WidgetStatePropertyAll( - effectiveBarPadding, - ), - leading: widget.viewLeading ?? defaultLeading, - trailing: widget.viewTrailing ?? defaultTrailing, - hintText: widget.viewHintText, - backgroundColor: const MaterialStatePropertyAll( - Colors.transparent, + return LayoutBuilder( + builder: (BuildContext context, BoxConstraints constraints) { + return Align( + alignment: Alignment.topLeft, + child: Transform.translate( + offset: _viewRect.topLeft, + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: minWidth, + maxWidth: _viewRect.width, + minHeight: minHeight, + maxHeight: widget.showFullScreenView + ? math.max(constraints.maxHeight, minHeight) + : _viewRect.height, + ), + child: Padding( + padding: widget.showFullScreenView + ? EdgeInsets.zero + : (effectivePadding ?? EdgeInsets.zero), + child: Material( + clipBehavior: Clip.antiAlias, + shape: effectiveShape, + color: effectiveBackgroundColor, + surfaceTintColor: effectiveSurfaceTint, + elevation: effectiveElevation, + child: OverflowBox( + alignment: Alignment.topLeft, + maxWidth: widget.showFullScreenView + ? constraints.maxWidth + : math.min(widget.viewMaxWidth, constraints.maxWidth), + minWidth: 0, + fit: OverflowBoxFit.deferToChild, + child: FadeTransition( + opacity: viewIconsFadeCurve, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: EdgeInsets.only(top: widget.topPadding), + child: SafeArea( + top: false, + bottom: false, + child: SearchBar( + autoFocus: true, + constraints: + headerConstraints ?? + (widget.showFullScreenView + ? BoxConstraints( + minHeight: _SearchViewDefaultsM3.fullScreenBarHeight, + ) + : null), + padding: WidgetStatePropertyAll( + effectiveBarPadding, + ), + leading: widget.viewLeading ?? defaultLeading, + trailing: widget.viewTrailing ?? defaultTrailing, + hintText: widget.viewHintText, + backgroundColor: const MaterialStatePropertyAll( + Colors.transparent, + ), + overlayColor: const MaterialStatePropertyAll( + Colors.transparent, + ), + elevation: const MaterialStatePropertyAll(0.0), + textStyle: MaterialStatePropertyAll(effectiveTextStyle), + hintStyle: MaterialStatePropertyAll(effectiveHintStyle), + controller: _controller, + onChanged: (String value) { + widget.viewOnChanged?.call(value); + updateSuggestions(); + }, + onSubmitted: widget.viewOnSubmitted, + textCapitalization: widget.textCapitalization, + textInputAction: widget.textInputAction, + keyboardType: widget.keyboardType, + smartDashesType: widget.smartDashesType, + smartQuotesType: widget.smartQuotesType, + ), ), - overlayColor: const MaterialStatePropertyAll(Colors.transparent), - elevation: const MaterialStatePropertyAll(0.0), - textStyle: MaterialStatePropertyAll(effectiveTextStyle), - hintStyle: MaterialStatePropertyAll(effectiveHintStyle), - controller: _controller, - onChanged: (String value) { - widget.viewOnChanged?.call(value); - updateSuggestions(); - }, - onSubmitted: widget.viewOnSubmitted, - textCapitalization: widget.textCapitalization, - textInputAction: widget.textInputAction, - keyboardType: widget.keyboardType, - smartDashesType: widget.smartDashesType, - smartQuotesType: widget.smartQuotesType, ), - ), + if (!effectiveShrinkWrap || + minHeight > 0 || + widget.showFullScreenView || + result.isNotEmpty) ...[ + FadeTransition(opacity: viewDividerFadeCurve, child: viewDivider), + Flexible( + fit: (effectiveShrinkWrap && !widget.showFullScreenView) + ? FlexFit.loose + : FlexFit.tight, + child: FadeTransition( + opacity: viewListFadeOnIntervalCurve, + child: widget.viewBuilder == null + ? MediaQuery.removePadding( + context: context, + removeTop: true, + child: ListView( + padding: EdgeInsets.only( + bottom: MediaQuery.viewInsetsOf(context).bottom, + ), + shrinkWrap: effectiveShrinkWrap, + children: result.toList(), + ), + ) + : widget.viewBuilder!(result), + ), + ), + ], + ], ), - if (!effectiveShrinkWrap || - minHeight > 0 || - widget.showFullScreenView || - result.isNotEmpty) ...[ - FadeTransition(opacity: viewDividerFadeCurve, child: viewDivider), - Flexible( - fit: (effectiveShrinkWrap && !widget.showFullScreenView) - ? FlexFit.loose - : FlexFit.tight, - child: FadeTransition( - opacity: viewListFadeOnIntervalCurve, - child: widget.viewBuilder == null - ? MediaQuery.removePadding( - context: context, - removeTop: true, - child: ListView( - padding: EdgeInsets.only( - bottom: MediaQuery.viewInsetsOf(context).bottom, - ), - shrinkWrap: effectiveShrinkWrap, - children: result.toList(), - ), - ) - : widget.viewBuilder!(result), - ), - ), - ], - ], + ), ), ), ), ), ), - ), - ), + ); + }, ); } } diff --git a/packages/material_ui/test/search_anchor_test.dart b/packages/material_ui/test/search_anchor_test.dart index 273edb806f5e..580b6c185671 100644 --- a/packages/material_ui/test/search_anchor_test.dart +++ b/packages/material_ui/test/search_anchor_test.dart @@ -4436,6 +4436,74 @@ void main() { expect(rotatedSize.width, landscapeModeWidth); expect(rotatedSize.height, landscapeModeHeight); }); + + testWidgets('SearchAnchor full-screen height matches resized parent height', ( + WidgetTester tester, + ) async { + addTearDown(tester.view.reset); + + var parentHeight = 400.0; + late StateSetter setState; + + await tester.pumpWidget( + MaterialApp( + builder: (BuildContext context, Widget? child) { + return Scaffold( + body: StatefulBuilder( + builder: (BuildContext context, StateSetter stateSetter) { + setState = stateSetter; + return SizedBox(height: parentHeight, width: 800.0, child: child); + }, + ), + ); + }, + home: Material( + child: SearchAnchor( + isFullScreen: true, + builder: (BuildContext context, SearchController controller) { + return IconButton( + icon: const Icon(Icons.search), + onPressed: () { + controller.openView(); + }, + ); + }, + suggestionsBuilder: (BuildContext context, SearchController controller) { + return []; + }, + ), + ), + ), + ); + + // Open search view. + await tester.tap(find.byIcon(Icons.search)); + await tester.pumpAndSettle(); + + // Verify search view height matches parent height (400.0). + Size size = getSearchViewSize(tester); + expect(size.height, 400.0); + + // Resize the parent container to 500.0. + setState(() { + parentHeight = 500.0; + }); + await tester.pumpAndSettle(); + + // Verify the view expands to 500.0. + size = getSearchViewSize(tester); + expect(size.height, 500.0); + + // Resize the parent container to 300.0. + setState(() { + parentHeight = 300.0; + }); + await tester.pumpAndSettle(); + + // Verify the view shrinks to 300.0. + size = getSearchViewSize(tester); + expect(size.height, 300.0); + }); } Future checkSearchBarDefaults( From dd072c011cd4ad8b2ced02b6d591be67d9629361 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Mon, 18 May 2026 17:16:41 -0700 Subject: [PATCH 5/7] Update test --- .../material_ui/test/search_anchor_test.dart | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/packages/material_ui/test/search_anchor_test.dart b/packages/material_ui/test/search_anchor_test.dart index 580b6c185671..912c25e11fe8 100644 --- a/packages/material_ui/test/search_anchor_test.dart +++ b/packages/material_ui/test/search_anchor_test.dart @@ -4437,6 +4437,7 @@ void main() { expect(rotatedSize.height, landscapeModeHeight); }); + // Regression test for https://github.com/flutter/flutter/issues/186154. testWidgets('SearchAnchor full-screen height matches resized parent height', ( WidgetTester tester, ) async { @@ -4447,30 +4448,40 @@ void main() { await tester.pumpWidget( MaterialApp( - builder: (BuildContext context, Widget? child) { - return Scaffold( - body: StatefulBuilder( - builder: (BuildContext context, StateSetter stateSetter) { - setState = stateSetter; - return SizedBox(height: parentHeight, width: 800.0, child: child); - }, - ), - ); - }, - home: Material( - child: SearchAnchor( - isFullScreen: true, - builder: (BuildContext context, SearchController controller) { - return IconButton( - icon: const Icon(Icons.search), - onPressed: () { - controller.openView(); - }, + home: Scaffold( + body: StatefulBuilder( + builder: (BuildContext context, StateSetter stateSetter) { + setState = stateSetter; + return SizedBox( + height: parentHeight, + width: 800.0, + child: Navigator( + onGenerateRoute: (RouteSettings settings) { + return MaterialPageRoute( + builder: (BuildContext context) { + return Scaffold( + body: SearchAnchor( + isFullScreen: true, + builder: (BuildContext context, SearchController controller) { + return IconButton( + icon: const Icon(Icons.search), + onPressed: () { + controller.openView(); + }, + ); + }, + suggestionsBuilder: + (BuildContext context, SearchController controller) { + return []; + }, + ), + ); + }, + ); + }, + ), ); }, - suggestionsBuilder: (BuildContext context, SearchController controller) { - return []; - }, ), ), ), From 8252a8698b57dda9ea833de5bf48587b3189aa6e Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Tue, 19 May 2026 09:32:35 -0700 Subject: [PATCH 6/7] Fix resizing navigator horizontally as well --- .../material_ui/lib/src/search_anchor.dart | 4 +++- .../material_ui/test/search_anchor_test.dart | 22 +++++++++++-------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/packages/material_ui/lib/src/search_anchor.dart b/packages/material_ui/lib/src/search_anchor.dart index 95e7dc175806..c3e27270cab4 100644 --- a/packages/material_ui/lib/src/search_anchor.dart +++ b/packages/material_ui/lib/src/search_anchor.dart @@ -1147,7 +1147,9 @@ class _ViewContentState extends State<_ViewContent> { child: ConstrainedBox( constraints: BoxConstraints( minWidth: minWidth, - maxWidth: _viewRect.width, + maxWidth: widget.showFullScreenView + ? math.max(constraints.maxWidth, minWidth) + : _viewRect.width, minHeight: minHeight, maxHeight: widget.showFullScreenView ? math.max(constraints.maxHeight, minHeight) diff --git a/packages/material_ui/test/search_anchor_test.dart b/packages/material_ui/test/search_anchor_test.dart index 912c25e11fe8..7e25e946d67f 100644 --- a/packages/material_ui/test/search_anchor_test.dart +++ b/packages/material_ui/test/search_anchor_test.dart @@ -4438,12 +4438,11 @@ void main() { }); // Regression test for https://github.com/flutter/flutter/issues/186154. - testWidgets('SearchAnchor full-screen height matches resized parent height', ( - WidgetTester tester, - ) async { + testWidgets('SearchAnchor resizes itself to match Navigator parent', (WidgetTester tester) async { addTearDown(tester.view.reset); var parentHeight = 400.0; + var parentWidth = 600.0; late StateSetter setState; await tester.pumpWidget( @@ -4454,7 +4453,7 @@ void main() { setState = stateSetter; return SizedBox( height: parentHeight, - width: 800.0, + width: parentWidth, child: Navigator( onGenerateRoute: (RouteSettings settings) { return MaterialPageRoute( @@ -4491,29 +4490,34 @@ void main() { await tester.tap(find.byIcon(Icons.search)); await tester.pumpAndSettle(); - // Verify search view height matches parent height (400.0). + // Verify search view size matches parent. Size size = getSearchViewSize(tester); expect(size.height, 400.0); + expect(size.width, 600.0); - // Resize the parent container to 500.0. + // Resize the parent container larger. setState(() { parentHeight = 500.0; + parentWidth = 700.0; }); await tester.pumpAndSettle(); - // Verify the view expands to 500.0. + // Verify the view expands to match parent. size = getSearchViewSize(tester); expect(size.height, 500.0); + expect(size.width, 700.0); - // Resize the parent container to 300.0. + // Resize the parent container smaller. setState(() { parentHeight = 300.0; + parentWidth = 400.0; }); await tester.pumpAndSettle(); - // Verify the view shrinks to 300.0. + // Verify the view shrinks to match parent. size = getSearchViewSize(tester); expect(size.height, 300.0); + expect(size.width, 400.0); }); } From 6bba12d53496d24839894fe5c2368d4ac263bf06 Mon Sep 17 00:00:00 2001 From: Elliott Brooks <21270878+elliette@users.noreply.github.com> Date: Thu, 13 Aug 2026 12:34:26 -0700 Subject: [PATCH 7/7] Add CHANGELOG entry, remove accidental merge conflict code --- .../pending_changelogs/change_2026_08_13_1786649533919.yaml | 4 ++++ packages/material_ui/test/search_anchor_test.dart | 2 -- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 packages/material_ui/pending_changelogs/change_2026_08_13_1786649533919.yaml diff --git a/packages/material_ui/pending_changelogs/change_2026_08_13_1786649533919.yaml b/packages/material_ui/pending_changelogs/change_2026_08_13_1786649533919.yaml new file mode 100644 index 000000000000..6bc5100c70f5 --- /dev/null +++ b/packages/material_ui/pending_changelogs/change_2026_08_13_1786649533919.yaml @@ -0,0 +1,4 @@ +changelog: | + - SearchAnchor overlay expands to full-screen on viewport size change (e.g., on device rotation). + - Fixes https://github.com/flutter/flutter/issues/186154. +version: patch diff --git a/packages/material_ui/test/search_anchor_test.dart b/packages/material_ui/test/search_anchor_test.dart index 7e25e946d67f..aa6934b18935 100644 --- a/packages/material_ui/test/search_anchor_test.dart +++ b/packages/material_ui/test/search_anchor_test.dart @@ -3533,8 +3533,6 @@ void main() { await tester.pump(); expect(focusNode.hasPrimaryFocus, isTrue); - await tester.tapAt(const Offset(50, 50)); - await tester.pump(); await tester.tapAt(const Offset(50, 50)); await tester.pump();