@@ -148,6 +148,7 @@ class SearchAnchor extends StatefulWidget {
148148 TextStyle ? viewHeaderHintStyle,
149149 Color ? dividerColor,
150150 BoxConstraints ? constraints,
151+ BoxConstraints ? viewConstraints,
151152 bool ? isFullScreen,
152153 SearchController searchController,
153154 required SuggestionsBuilder suggestionsBuilder
@@ -254,6 +255,11 @@ class SearchAnchor extends StatefulWidget {
254255
255256 /// Optional size constraints for the search view.
256257 ///
258+ /// By default, the search view has the same width as the anchor and is 2/3
259+ /// the height of the screen. If the width and height of the view are within
260+ /// the [viewConstraints] , the view will show its default size. Otherwise,
261+ /// the size of the view will be constrained by this property.
262+ ///
257263 /// If null, the value of [SearchViewThemeData.constraints] will be used. If
258264 /// this is also null, then the constraints defaults to:
259265 /// ```dart
@@ -477,24 +483,43 @@ class _SearchViewRoute extends PopupRoute<_SearchViewRoute> {
477483 final Size screenSize = MediaQuery .of (context).size;
478484 final Rect anchorRect = getRect () ?? Rect .zero;
479485
480- // Check if the search view goes off the screen.
481486 final BoxConstraints effectiveConstraints = viewConstraints ?? viewTheme.constraints ?? viewDefaults.constraints! ;
482- final double verticalDistanceToEdge = screenSize.height - anchorRect.top;
483- final double endHeight = math.max (effectiveConstraints.minHeight, math.min (screenSize.height * 2 / 3 , verticalDistanceToEdge));
484487 _rectTween.begin = anchorRect;
485488
489+ final double viewWidth = clampDouble (anchorRect.width, effectiveConstraints.minWidth, effectiveConstraints.maxWidth);
490+ final double viewHeight = clampDouble (screenSize.height * 2 / 3 , effectiveConstraints.minHeight, effectiveConstraints.maxHeight);
491+
486492 switch (textDirection ?? TextDirection .ltr) {
487493 case TextDirection .ltr:
488- final double viewEdgeToScreenEdge = screenSize.width - anchorRect.left;
489- final double endWidth = math.max (effectiveConstraints.minWidth, math.min (anchorRect.width, viewEdgeToScreenEdge));
490- final Size endSize = Size (endWidth, endHeight);
491- _rectTween.end = showFullScreenView ? Offset .zero & screenSize : (anchorRect.topLeft & endSize);
494+ final double viewLeftToScreenRight = screenSize.width - anchorRect.left;
495+ final double viewTopToScreenBottom = screenSize.height - anchorRect.top;
496+
497+ // Make sure the search view doesn't go off the screen. If the search view
498+ // doesn't fit, move the top-left corner of the view to fit the window.
499+ // If the window is smaller than the view, then we resize the view to fit the window.
500+ Offset topLeft = anchorRect.topLeft;
501+ if (viewLeftToScreenRight < viewWidth) {
502+ topLeft = Offset (screenSize.width - math.min (viewWidth, screenSize.width), topLeft.dy);
503+ }
504+ if (viewTopToScreenBottom < viewHeight) {
505+ topLeft = Offset (topLeft.dx, screenSize.height - math.min (viewHeight, screenSize.height));
506+ }
507+ final Size endSize = Size (viewWidth, viewHeight);
508+ _rectTween.end = showFullScreenView ? Offset .zero & screenSize : (topLeft & endSize);
492509 return ;
493510 case TextDirection .rtl:
494- final double viewEdgeToScreenEdge = anchorRect.right;
495- final double endWidth = math.max (effectiveConstraints.minWidth, math.min (anchorRect.width, viewEdgeToScreenEdge));
496- final Offset topLeft = Offset (math.max (anchorRect.right - endWidth, 0.0 ), anchorRect.top);
497- final Size endSize = Size (endWidth, endHeight);
511+ final double viewRightToScreenLeft = anchorRect.right;
512+ final double viewTopToScreenBottom = screenSize.height - anchorRect.top;
513+
514+ // Make sure the search view doesn't go off the screen.
515+ Offset topLeft = Offset (math.max (anchorRect.right - viewWidth, 0.0 ), anchorRect.top);
516+ if (viewRightToScreenLeft < viewWidth) {
517+ topLeft = Offset (0.0 , topLeft.dy);
518+ }
519+ if (viewTopToScreenBottom < viewHeight) {
520+ topLeft = Offset (topLeft.dx, screenSize.height - math.min (viewHeight, screenSize.height));
521+ }
522+ final Size endSize = Size (viewWidth, viewHeight);
498523 _rectTween.end = showFullScreenView ? Offset .zero & screenSize : (topLeft & endSize);
499524 }
500525 }
@@ -626,7 +651,6 @@ class _ViewContentState extends State<_ViewContent> {
626651 super .initState ();
627652 _viewRect = widget.viewRect;
628653 _controller = widget.searchController;
629- result = widget.suggestionsBuilder (context, _controller);
630654 if (! _focusNode.hasFocus) {
631655 _focusNode.requestFocus ();
632656 }
@@ -645,20 +669,45 @@ class _ViewContentState extends State<_ViewContent> {
645669 @override
646670 void didChangeDependencies () {
647671 super .didChangeDependencies ();
672+ result = widget.suggestionsBuilder (context, _controller);
648673 final Size updatedScreenSize = MediaQuery .of (context).size;
674+
649675 if (_screenSize != updatedScreenSize) {
650676 _screenSize = updatedScreenSize;
651677 setState (() {
652678 final Rect anchorRect = widget.getRect () ?? _viewRect;
653679 final BoxConstraints constraints = widget.viewConstraints ?? widget.viewTheme.constraints ?? widget.viewDefaults.constraints! ;
654- final Size updatedViewSize = Size (math.max (constraints.minWidth, anchorRect.width), _viewRect.height);
680+ final double viewWidth = clampDouble (anchorRect.width, constraints.minWidth, constraints.maxWidth);
681+ final double viewHeight = clampDouble (_screenSize! .height * 2 / 3 , constraints.minHeight, constraints.maxHeight);
682+ final Size updatedViewSize = Size (viewWidth, viewHeight);
683+
655684 switch (Directionality .of (context)) {
656685 case TextDirection .ltr:
657- final Offset updatedPosition = anchorRect.topLeft;
658- _viewRect = updatedPosition & updatedViewSize;
686+ final double viewLeftToScreenRight = _screenSize! .width - anchorRect.left;
687+ final double viewTopToScreenBottom = _screenSize! .height - anchorRect.top;
688+
689+ // Make sure the search view doesn't go off the screen when the screen
690+ // size is changed. If the search view doesn't fit, move the top-left
691+ // corner of the view to fit the window. If the window is smaller than
692+ // the view, then we resize the view to fit the window.
693+ Offset topLeft = anchorRect.topLeft;
694+ if (viewLeftToScreenRight < viewWidth) {
695+ topLeft = Offset (_screenSize! .width - math.min (viewWidth, _screenSize! .width), anchorRect.top);
696+ }
697+ if (viewTopToScreenBottom < viewHeight) {
698+ topLeft = Offset (topLeft.dx, _screenSize! .height - math.min (viewHeight, _screenSize! .height));
699+ }
700+ _viewRect = topLeft & updatedViewSize;
659701 return ;
660702 case TextDirection .rtl:
661- final Offset topLeft = Offset (math.max (anchorRect.right - updatedViewSize.width, 0.0 ), anchorRect.top);
703+ final double viewTopToScreenBottom = _screenSize! .height - anchorRect.top;
704+ Offset topLeft = Offset (
705+ math.max (anchorRect.right - viewWidth, 0.0 ),
706+ anchorRect.top,
707+ );
708+ if (viewTopToScreenBottom < viewHeight) {
709+ topLeft = Offset (topLeft.dx, _screenSize! .height - math.min (viewHeight, _screenSize! .height));
710+ }
662711 _viewRect = topLeft & updatedViewSize;
663712 }
664713 });
@@ -834,6 +883,7 @@ class _SearchAnchorWithSearchBar extends SearchAnchor {
834883 TextStyle ? viewHeaderHintStyle,
835884 super .dividerColor,
836885 BoxConstraints ? constraints,
886+ super .viewConstraints,
837887 super .isFullScreen,
838888 super .searchController,
839889 required super .suggestionsBuilder
0 commit comments