diff --git a/packages/flutter/lib/src/cupertino/nav_bar.dart b/packages/flutter/lib/src/cupertino/nav_bar.dart index 286172bd11..4ad073c520 100644 --- a/packages/flutter/lib/src/cupertino/nav_bar.dart +++ b/packages/flutter/lib/src/cupertino/nav_bar.dart @@ -728,6 +728,7 @@ class _CupertinoNavigationBarState extends State { userTrailing: widget.trailing, padding: widget.padding, userLargeTitle: widget.largeTitle, + userBottom: widget.bottom, large: widget.largeTitle != null, staticBar: true, // This one does not scroll context: context, @@ -764,7 +765,8 @@ class _CupertinoNavigationBarState extends State { ), ), ), - if (widget.bottom != null) SizedBox(height: bottomHeight, child: widget.bottom), + if (widget.bottom != null) + SizedBox(height: bottomHeight, child: components.navBarBottom), ], ), ); @@ -775,7 +777,8 @@ class _CupertinoNavigationBarState extends State { child: Column( children: [ navBar, - if (widget.bottom != null) SizedBox(height: bottomHeight, child: widget.bottom), + if (widget.bottom != null) + SizedBox(height: bottomHeight, child: components.navBarBottom), ], ), ); @@ -1265,6 +1268,23 @@ class _CupertinoSliverNavigationBarState extends State( + find.ancestor( + of: flying(tester, find.text('Page 2')), + matching: find.byType(FadeTransition), + ), + ) + .opacity + .value; + + checkOpacity(tester, flying(tester, find.byType(Placeholder)), largeTitleOpacity); + + Offset largeTitleOffset = tester.getTopLeft(flying(tester, find.text('Page 2'))); + + // The nav bar bottom is horizontally aligned to the large title. + expect( + tester.getTopLeft(flying(tester, find.byType(Placeholder))).dx, + largeTitleOffset.dx - horizontalPadding, + ); + + await tester.pump(const Duration(milliseconds: 150)); + + checkOpacity(tester, flying(tester, find.byType(Placeholder)), 0.444); + + largeTitleOffset = tester.getTopLeft(flying(tester, find.text('Page 2'))); + + // The nav bar bottom is horizontally aligned to the large title. + expect( + tester.getTopLeft(flying(tester, find.byType(Placeholder))).dx, + largeTitleOffset.dx - horizontalPadding, + ); + }); + + testWidgets('Top CupertinoNavigationBar.bottom fades and slides in to the right', ( + WidgetTester tester, + ) async { + await startTransitionBetween( + tester, + toTitle: 'Page 2', + to: const CupertinoNavigationBar( + bottom: PreferredSize(preferredSize: Size.fromHeight(30.0), child: Placeholder()), + ), + ); + + await tester.pump(const Duration(milliseconds: 50)); + + expect(flying(tester, find.text('Page 2')), findsOneWidget); + expect(flying(tester, find.byType(Placeholder)), findsOneWidget); + + checkOpacity(tester, flying(tester, find.byType(Placeholder)), 0.001); + + expect( + tester.getTopLeft(flying(tester, find.byType(Placeholder))).dx, + moreOrLessEquals(779.42, epsilon: 0.01), + ); + + await tester.pump(const Duration(milliseconds: 150)); + + checkOpacity(tester, flying(tester, find.byType(Placeholder)), 0.444); + + expect( + tester.getTopLeft(flying(tester, find.byType(Placeholder))).dx, + moreOrLessEquals(309.30, epsilon: 0.01), + ); + }); + + testWidgets('Searchable-to-searchable transition does not fade', (WidgetTester tester) async { + await startTransitionBetween( + tester, + from: const CupertinoSliverNavigationBar.search(searchField: CupertinoSearchTextField()), + to: const CupertinoSliverNavigationBar.search(searchField: CupertinoSearchTextField()), + fromTitle: 'Page 1', + toTitle: 'Page 2', + ); + + await tester.pump(const Duration(milliseconds: 50)); + + expect(flying(tester, find.byType(CupertinoSearchTextField)), findsNWidgets(2)); + + // Either no FadeTransition ancestor is found, or one is found but there is no fade. + expect( + find.ancestor( + of: find.byType(CupertinoSearchTextField).first, + matching: find.byType(FadeTransition), + ), + findsNothing, + ); + checkOpacity(tester, flying(tester, find.byType(CupertinoSearchTextField).last), 1.0); + + await tester.pump(const Duration(milliseconds: 150)); + + // Either no FadeTransition ancestor is found, or one is found but there is no fade. + expect( + find.ancestor( + of: find.byType(CupertinoSearchTextField).first, + matching: find.byType(FadeTransition), + ), + findsNothing, + ); + checkOpacity(tester, flying(tester, find.byType(CupertinoSearchTextField).last), 1.0); + }); + testWidgets('Components are not unnecessarily rebuilt during transitions', ( WidgetTester tester, ) async {