Correct max height calculation to fade and animate insets on scroll in CupertinoSearchTextField (#166569)

Fixes [CupertinoSliverNavigationBar.search does not fade or animate
insets if search view scrolled in automatic
mode](https://github.com/flutter/flutter/issues/165152)

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [ ] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
diff --git a/packages/flutter/lib/src/cupertino/search_field.dart b/packages/flutter/lib/src/cupertino/search_field.dart
index aba2788..d13524d 100644
--- a/packages/flutter/lib/src/cupertino/search_field.dart
+++ b/packages/flutter/lib/src/cupertino/search_field.dart
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:math' as math;
+
 import 'package:flutter/services.dart';
 import 'package:flutter/widgets.dart';
 
@@ -363,8 +365,8 @@
   TextEditingController get _effectiveController => widget.controller ?? _controller!.value;
 
   ScrollNotificationObserverState? _scrollNotificationObserver;
+  late double _scaledIconSize;
   double _fadeExtent = 0.0;
-  double? _maxHeight;
 
   @override
   void initState() {
@@ -441,12 +443,13 @@
   }
 
   void _handleScrollNotification(ScrollNotification notification) {
-    if (_maxHeight == null) {
-      _maxHeight ??= context.size?.height;
-    } else if (notification is ScrollUpdateNotification) {
+    if (notification is ScrollUpdateNotification) {
       final double currentHeight = context.size?.height ?? 0.0;
       setState(() {
-        _fadeExtent = _calculateScrollOpacity(currentHeight, _maxHeight!);
+        _fadeExtent = _calculateScrollOpacity(
+          currentHeight,
+          _scaledIconSize + math.max(widget.prefixInsets.vertical, widget.suffixInsets.vertical),
+        );
       });
     }
   }
@@ -487,7 +490,7 @@
 
     // The icon size will be scaled by a factor of the accessibility text scale,
     // to follow the behavior of `UISearchTextField`.
-    final double scaledIconSize = MediaQuery.textScalerOf(context).scale(widget.itemSize);
+    _scaledIconSize = MediaQuery.textScalerOf(context).scale(widget.itemSize);
 
     // If decoration was not provided, create a decoration with the provided
     // background color and border radius.
@@ -500,7 +503,7 @@
 
     final IconThemeData iconThemeData = IconThemeData(
       color: CupertinoDynamicColor.resolve(widget.itemColor, context),
-      size: scaledIconSize,
+      size: _scaledIconSize,
     );
 
     final Widget prefix = Opacity(
diff --git a/packages/flutter/test/cupertino/search_field_test.dart b/packages/flutter/test/cupertino/search_field_test.dart
index f209d3c..03666fd 100644
--- a/packages/flutter/test/cupertino/search_field_test.dart
+++ b/packages/flutter/test/cupertino/search_field_test.dart
@@ -749,4 +749,67 @@
       lessThan(initialPadding),
     );
   });
+
+  testWidgets('Fades and animates insets on scroll if search field starts out collapsed', (
+    WidgetTester tester,
+  ) async {
+    const TextDirection direction = TextDirection.ltr;
+    const double scrollOffset = 200;
+    await tester.pumpWidget(
+      const Directionality(
+        textDirection: direction,
+        child: CupertinoApp(
+          home: CupertinoPageScaffold(
+            child: CustomScrollView(
+              slivers: <Widget>[
+                CupertinoSliverNavigationBar.search(
+                  largeTitle: Text('Large title'),
+                  searchField: CupertinoSearchTextField(),
+                ),
+                SliverToBoxAdapter(child: SizedBox(height: 1000)),
+              ],
+            ),
+          ),
+        ),
+      ),
+    );
+
+    final Finder searchTextFieldFinder = find.byType(CupertinoSearchTextField);
+    expect(searchTextFieldFinder, findsOneWidget);
+
+    final double searchTextFieldHeight = tester.getSize(searchTextFieldFinder).height;
+    await tester.tap(find.widgetWithText(CupertinoSearchTextField, 'Search'), warnIfMissed: false);
+
+    final TestGesture scrollGesture1 = await tester.startGesture(
+      tester.getCenter(find.byType(CustomScrollView)),
+    );
+    await scrollGesture1.moveBy(const Offset(0, -scrollOffset));
+    await scrollGesture1.up();
+    await tester.pumpAndSettle();
+
+    expect(find.text('Cancel'), findsOneWidget);
+    await tester.tap(find.text('Cancel'));
+    await tester.pumpAndSettle();
+
+    final TestGesture scrollGesture2 = await tester.startGesture(
+      tester.getCenter(find.byType(CustomScrollView)),
+    );
+    await scrollGesture2.moveBy(Offset(0, scrollOffset - searchTextFieldHeight / 2));
+    await scrollGesture2.up();
+    await tester.pump();
+
+    final Finder prefixIconFinder = find.descendant(
+      of: searchTextFieldFinder,
+      matching: find.byIcon(CupertinoIcons.search),
+    );
+
+    // The prefix icon has faded.
+    expect(prefixIconFinder, findsOneWidget);
+    expect(
+      tester
+          .widget<Opacity>(find.ancestor(of: prefixIconFinder, matching: find.byType(Opacity)))
+          .opacity,
+      lessThan(1.0),
+    );
+  });
 }