mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Condense nav bar large title in landscape mode (#166956)
## Rotation demo https://github.com/user-attachments/assets/b59d6875-dff7-4b40-9525-565dfd8a2554 ### Portrait mode .automatic https://github.com/user-attachments/assets/88f4f3a2-0f13-4c92-b601-20c20e13f7dc ### Landscape mode .automatic https://github.com/user-attachments/assets/dd5e2373-82e3-41fc-8e83-4002ce5e848e ### Portrait mode .always https://github.com/user-attachments/assets/623d131a-f71b-430d-b84c-0b4519919f56 ### Landscape mode .always https://github.com/user-attachments/assets/5980e8fe-a981-482d-9f77-97f9ab7495c7 Fixes [CupertinoSliverNavigationBar doesn't become compact in landscape mode](https://github.com/flutter/flutter/issues/39254) <details> <summary>Sample code</summary> ```dart import 'package:flutter/cupertino.dart'; void main() => runApp(const NavBarBlueApp()); class NavBarBlueApp extends StatelessWidget { const NavBarBlueApp({super.key}); @override Widget build(BuildContext context) { return CupertinoApp( theme: CupertinoThemeData(), home: MainPage(), ); } } class MainPage extends StatelessWidget { const MainPage({super.key}); @override Widget build(BuildContext context) { return CupertinoPageScaffold( child: SafeArea( child: CustomScrollView( slivers: [ CupertinoSliverNavigationBar.search( stretch: true, searchField: CupertinoSearchTextField( suffixMode: OverlayVisibilityMode.always, suffixIcon: Icon( CupertinoIcons.mic_solid, )), largeTitle: Text('Lists'), bottomMode: NavigationBarBottomMode.always, ), SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { return CupertinoListTile( title: Text('Entry $index'), ); }, childCount: 20, ), ), ], ), ), ); } } ``` </details>
This commit is contained in:
parent
651ff0a8f2
commit
96d1b99211
@ -12,6 +12,10 @@ void main() {
|
|||||||
// The point is to mainly test the cupertino icons that we don't have a
|
// The point is to mainly test the cupertino icons that we don't have a
|
||||||
// dependency against in the flutter/cupertino package directly.
|
// dependency against in the flutter/cupertino package directly.
|
||||||
|
|
||||||
|
// Set window orientation to portrait.
|
||||||
|
tester.view.physicalSize = const Size(2400.0, 3000.0);
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
|
||||||
final Future<ByteData> font = rootBundle.load(
|
final Future<ByteData> font = rootBundle.load(
|
||||||
'packages/cupertino_icons/assets/CupertinoIcons.ttf',
|
'packages/cupertino_icons/assets/CupertinoIcons.ttf',
|
||||||
);
|
);
|
||||||
|
@ -8,10 +8,16 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
|
|
||||||
const Offset dragUp = Offset(0.0, -150.0);
|
const Offset dragUp = Offset(0.0, -150.0);
|
||||||
|
|
||||||
|
void setWindowToPortrait(WidgetTester tester, {Size size = const Size(2400.0, 3000.0)}) {
|
||||||
|
tester.view.physicalSize = size;
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Collapse and expand CupertinoSliverNavigationBar changes title position', (
|
testWidgets('Collapse and expand CupertinoSliverNavigationBar changes title position', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Large title is visible and at lower position.
|
// Large title is visible and at lower position.
|
||||||
@ -29,6 +35,7 @@ void main() {
|
|||||||
testWidgets('Middle widget is visible in both collapsed and expanded states', (
|
testWidgets('Middle widget is visible in both collapsed and expanded states', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Navigate to a page that has both middle and large titles.
|
// Navigate to a page that has both middle and large titles.
|
||||||
@ -55,6 +62,7 @@ void main() {
|
|||||||
testWidgets('CupertinoSliverNavigationBar with previous route has back button', (
|
testWidgets('CupertinoSliverNavigationBar with previous route has back button', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Navigate to a page that has back button
|
// Navigate to a page that has back button
|
||||||
|
@ -9,10 +9,16 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
const Offset titleDragUp = Offset(0.0, -100.0);
|
const Offset titleDragUp = Offset(0.0, -100.0);
|
||||||
const Offset bottomDragUp = Offset(0.0, -50.0);
|
const Offset bottomDragUp = Offset(0.0, -50.0);
|
||||||
|
|
||||||
|
void setWindowToPortrait(WidgetTester tester, {Size size = const Size(2400.0, 3000.0)}) {
|
||||||
|
tester.view.physicalSize = size;
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Collapse and expand CupertinoSliverNavigationBar changes title position', (
|
testWidgets('Collapse and expand CupertinoSliverNavigationBar changes title position', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Large title is visible and at lower position.
|
// Large title is visible and at lower position.
|
||||||
@ -28,6 +34,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Search field is hidden in bottom automatic mode', (WidgetTester tester) async {
|
testWidgets('Search field is hidden in bottom automatic mode', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Navigate to a page with bottom automatic mode.
|
// Navigate to a page with bottom automatic mode.
|
||||||
@ -64,6 +71,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Search field is always shown in bottom always mode', (WidgetTester tester) async {
|
testWidgets('Search field is always shown in bottom always mode', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Navigate to a page with bottom always mode.
|
// Navigate to a page with bottom always mode.
|
||||||
@ -92,6 +100,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Opens the search view when the search field is tapped', (WidgetTester tester) async {
|
testWidgets('Opens the search view when the search field is tapped', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Navigate to a page with a search field.
|
// Navigate to a page with a search field.
|
||||||
@ -131,6 +140,7 @@ void main() {
|
|||||||
testWidgets('CupertinoSliverNavigationBar with previous route has back button', (
|
testWidgets('CupertinoSliverNavigationBar with previous route has back button', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Navigate to the first page.
|
// Navigate to the first page.
|
||||||
|
@ -8,8 +8,14 @@ import 'package:flutter_test/flutter_test.dart';
|
|||||||
|
|
||||||
const Offset dragUp = Offset(0.0, -150.0);
|
const Offset dragUp = Offset(0.0, -150.0);
|
||||||
|
|
||||||
|
void setWindowToPortrait(WidgetTester tester, {Size size = const Size(2400.0, 3000.0)}) {
|
||||||
|
tester.view.physicalSize = size;
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('CupertinoSliverNavigationBar bottom widget', (WidgetTester tester) async {
|
testWidgets('CupertinoSliverNavigationBar bottom widget', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
final Finder preferredSize = find.byType(PreferredSize);
|
final Finder preferredSize = find.byType(PreferredSize);
|
||||||
@ -24,6 +30,7 @@ void main() {
|
|||||||
testWidgets('Collapse and expand CupertinoSliverNavigationBar changes title position', (
|
testWidgets('Collapse and expand CupertinoSliverNavigationBar changes title position', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Large title is visible and at lower position.
|
// Large title is visible and at lower position.
|
||||||
@ -41,6 +48,7 @@ void main() {
|
|||||||
testWidgets('Middle widget is visible in both collapsed and expanded states', (
|
testWidgets('Middle widget is visible in both collapsed and expanded states', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Navigate to a page that has both middle and large titles.
|
// Navigate to a page that has both middle and large titles.
|
||||||
@ -67,6 +75,7 @@ void main() {
|
|||||||
testWidgets('CupertinoSliverNavigationBar with previous route has back button', (
|
testWidgets('CupertinoSliverNavigationBar with previous route has back button', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(const example.SliverNavBarApp());
|
await tester.pumpWidget(const example.SliverNavBarApp());
|
||||||
|
|
||||||
// Navigate to a page that has a back button.
|
// Navigate to a page that has a back button.
|
||||||
|
@ -1149,11 +1149,13 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
|
|||||||
late _NavigationBarStaticComponentsKeys keys;
|
late _NavigationBarStaticComponentsKeys keys;
|
||||||
ScrollableState? _scrollableState;
|
ScrollableState? _scrollableState;
|
||||||
_NavigationBarSearchField? preferredSizeSearchField;
|
_NavigationBarSearchField? preferredSizeSearchField;
|
||||||
|
Widget? effectiveMiddle;
|
||||||
late AnimationController _animationController;
|
late AnimationController _animationController;
|
||||||
late CurvedAnimation _searchAnimation;
|
late CurvedAnimation _searchAnimation;
|
||||||
late Animation<double> persistentHeightAnimation;
|
late Animation<double> persistentHeightAnimation;
|
||||||
late Animation<double> largeTitleHeightAnimation;
|
late Animation<double> largeTitleHeightAnimation;
|
||||||
bool searchIsActive = false;
|
bool searchIsActive = false;
|
||||||
|
bool isPortrait = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -1169,6 +1171,14 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
|
isPortrait = MediaQuery.orientationOf(context) == Orientation.portrait;
|
||||||
|
final Tween<double> largeTitleHeightTween = Tween<double>(
|
||||||
|
begin: isPortrait ? _kNavBarLargeTitleHeightExtension : 0.0,
|
||||||
|
end: 0.0,
|
||||||
|
);
|
||||||
|
largeTitleHeightAnimation = largeTitleHeightTween.animate(_animationController);
|
||||||
|
effectiveMiddle = widget.middle ?? (isPortrait ? null : widget.largeTitle);
|
||||||
|
|
||||||
_scrollableState?.position.isScrollingNotifier.removeListener(_handleScrollChange);
|
_scrollableState?.position.isScrollingNotifier.removeListener(_handleScrollChange);
|
||||||
_scrollableState = Scrollable.maybeOf(context);
|
_scrollableState = Scrollable.maybeOf(context);
|
||||||
_scrollableState?.position.isScrollingNotifier.addListener(_handleScrollChange);
|
_scrollableState?.position.isScrollingNotifier.addListener(_handleScrollChange);
|
||||||
@ -1203,11 +1213,6 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
|
|||||||
);
|
);
|
||||||
persistentHeightAnimation = persistentHeightTween.animate(_animationController)
|
persistentHeightAnimation = persistentHeightTween.animate(_animationController)
|
||||||
..addStatusListener(_handleSearchFieldStatusChanged);
|
..addStatusListener(_handleSearchFieldStatusChanged);
|
||||||
final Tween<double> largeTitleHeightTween = Tween<double>(
|
|
||||||
begin: _kNavBarLargeTitleHeightExtension,
|
|
||||||
end: 0.0,
|
|
||||||
);
|
|
||||||
largeTitleHeightAnimation = largeTitleHeightTween.animate(_animationController);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleScrollChange() {
|
void _handleScrollChange() {
|
||||||
@ -1221,16 +1226,17 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
|
|||||||
widget.bottomMode == NavigationBarBottomMode.always ? 0.0 : _bottomHeight;
|
widget.bottomMode == NavigationBarBottomMode.always ? 0.0 : _bottomHeight;
|
||||||
final bool canScrollBottom =
|
final bool canScrollBottom =
|
||||||
(widget._searchable || widget.bottom != null) && bottomScrollOffset > 0.0;
|
(widget._searchable || widget.bottom != null) && bottomScrollOffset > 0.0;
|
||||||
|
final double effectiveLargeTitleHeight = isPortrait ? _kNavBarLargeTitleHeightExtension : 0.0;
|
||||||
|
|
||||||
// Snap the scroll view to a target determined by the navigation bar's
|
// Snap the scroll view to a target determined by the navigation bar's
|
||||||
// position.
|
// position.
|
||||||
if (canScrollBottom && position.pixels < bottomScrollOffset) {
|
if (canScrollBottom && position.pixels < bottomScrollOffset) {
|
||||||
target = position.pixels > bottomScrollOffset / 2 ? bottomScrollOffset : 0.0;
|
target = position.pixels > bottomScrollOffset / 2 ? bottomScrollOffset : 0.0;
|
||||||
} else if (position.pixels > bottomScrollOffset &&
|
} else if (position.pixels > bottomScrollOffset &&
|
||||||
position.pixels < bottomScrollOffset + _kNavBarLargeTitleHeightExtension) {
|
position.pixels < bottomScrollOffset + effectiveLargeTitleHeight) {
|
||||||
target =
|
target =
|
||||||
position.pixels > bottomScrollOffset + (_kNavBarLargeTitleHeightExtension / 2)
|
position.pixels > bottomScrollOffset + (effectiveLargeTitleHeight / 2)
|
||||||
? bottomScrollOffset + _kNavBarLargeTitleHeightExtension
|
? bottomScrollOffset + effectiveLargeTitleHeight
|
||||||
: bottomScrollOffset;
|
: bottomScrollOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1280,7 +1286,7 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
|
|||||||
automaticallyImplyLeading: widget.automaticallyImplyLeading,
|
automaticallyImplyLeading: widget.automaticallyImplyLeading,
|
||||||
automaticallyImplyTitle: widget.automaticallyImplyTitle,
|
automaticallyImplyTitle: widget.automaticallyImplyTitle,
|
||||||
previousPageTitle: widget.previousPageTitle,
|
previousPageTitle: widget.previousPageTitle,
|
||||||
userMiddle: _animationController.isAnimating ? const Text('') : widget.middle,
|
userMiddle: _animationController.isAnimating ? const Text('') : effectiveMiddle,
|
||||||
userTrailing:
|
userTrailing:
|
||||||
widget.trailing != null
|
widget.trailing != null
|
||||||
? Visibility(visible: !searchIsActive, child: widget.trailing!)
|
? Visibility(visible: !searchIsActive, child: widget.trailing!)
|
||||||
@ -1304,7 +1310,7 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
|
|||||||
: widget.bottom) ??
|
: widget.bottom) ??
|
||||||
const SizedBox.shrink(),
|
const SizedBox.shrink(),
|
||||||
padding: widget.padding,
|
padding: widget.padding,
|
||||||
large: true,
|
large: isPortrait,
|
||||||
staticBar: false, // This one scrolls.
|
staticBar: false, // This one scrolls.
|
||||||
context: context,
|
context: context,
|
||||||
);
|
);
|
||||||
@ -1318,7 +1324,7 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
|
|||||||
delegate: _LargeTitleNavigationBarSliverDelegate(
|
delegate: _LargeTitleNavigationBarSliverDelegate(
|
||||||
keys: keys,
|
keys: keys,
|
||||||
components: components,
|
components: components,
|
||||||
userMiddle: widget.middle,
|
userMiddle: effectiveMiddle,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
CupertinoDynamicColor.maybeResolve(widget.backgroundColor, context) ??
|
CupertinoDynamicColor.maybeResolve(widget.backgroundColor, context) ??
|
||||||
CupertinoTheme.of(context).barBackgroundColor,
|
CupertinoTheme.of(context).barBackgroundColor,
|
||||||
@ -1331,7 +1337,7 @@ class _CupertinoSliverNavigationBarState extends State<CupertinoSliverNavigation
|
|||||||
heroTag: widget.heroTag,
|
heroTag: widget.heroTag,
|
||||||
persistentHeight: persistentHeightAnimation.value + MediaQuery.paddingOf(context).top,
|
persistentHeight: persistentHeightAnimation.value + MediaQuery.paddingOf(context).top,
|
||||||
largeTitleHeight: largeTitleHeightAnimation.value,
|
largeTitleHeight: largeTitleHeightAnimation.value,
|
||||||
alwaysShowMiddle: widget.alwaysShowMiddle && widget.middle != null,
|
alwaysShowMiddle: widget.alwaysShowMiddle && effectiveMiddle != null,
|
||||||
stretchConfiguration:
|
stretchConfiguration:
|
||||||
widget.stretch && !searchIsActive ? OverScrollHeaderStretchConfiguration() : null,
|
widget.stretch && !searchIsActive ? OverScrollHeaderStretchConfiguration() : null,
|
||||||
enableBackgroundFilterBlur: widget.enableBackgroundFilterBlur,
|
enableBackgroundFilterBlur: widget.enableBackgroundFilterBlur,
|
||||||
|
@ -16,6 +16,11 @@ import '../widgets/semantics_tester.dart';
|
|||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
|
void setWindowToPortrait(WidgetTester tester, {Size size = const Size(2400.0, 3000.0)}) {
|
||||||
|
tester.view.physicalSize = size;
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Middle still in center with asymmetrical actions', (WidgetTester tester) async {
|
testWidgets('Middle still in center with asymmetrical actions', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@ -305,6 +310,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Can specify custom brightness', (WidgetTester tester) async {
|
testWidgets('Can specify custom brightness', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
const CupertinoApp(
|
const CupertinoApp(
|
||||||
home: CupertinoNavigationBar(
|
home: CupertinoNavigationBar(
|
||||||
@ -498,6 +504,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Large title nav bar scrolls', (WidgetTester tester) async {
|
testWidgets('Large title nav bar scrolls', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@ -573,6 +580,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('User specified middle is always visible in sliver', (WidgetTester tester) async {
|
testWidgets('User specified middle is always visible in sliver', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
final Key segmentedControlsKey = UniqueKey();
|
final Key segmentedControlsKey = UniqueKey();
|
||||||
@ -629,6 +637,7 @@ void main() {
|
|||||||
testWidgets(
|
testWidgets(
|
||||||
'User specified middle is only visible when sliver is collapsed if alwaysShowMiddle is false',
|
'User specified middle is only visible when sliver is collapsed if alwaysShowMiddle is false',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@ -682,6 +691,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
testWidgets('Small title can be overridden', (WidgetTester tester) async {
|
testWidgets('Small title can be overridden', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@ -1171,6 +1181,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Sliver large title golden', (WidgetTester tester) async {
|
testWidgets('Sliver large title golden', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
home: RepaintBoundary(
|
home: RepaintBoundary(
|
||||||
@ -1736,6 +1747,7 @@ void main() {
|
|||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
const Text trailingText = Text('Bar Button');
|
const Text trailingText = Text('Bar Button');
|
||||||
const Text titleText = Text('Large Title');
|
const Text titleText = Text('Large Title');
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -1874,6 +1886,7 @@ void main() {
|
|||||||
testWidgets(
|
testWidgets(
|
||||||
'CupertinoSliverNavigationBar magnifies upon over-scroll and shrinks back once over-scroll ends',
|
'CupertinoSliverNavigationBar magnifies upon over-scroll and shrinks back once over-scroll ends',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
const Text titleText = Text('Large Title');
|
const Text titleText = Text('Large Title');
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@ -1985,6 +1998,7 @@ void main() {
|
|||||||
const double largeTitleHeight = 44.0;
|
const double largeTitleHeight = 44.0;
|
||||||
const double bottomHeight = 10.0;
|
const double bottomHeight = 10.0;
|
||||||
final ScrollController controller = ScrollController();
|
final ScrollController controller = ScrollController();
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -2042,6 +2056,7 @@ void main() {
|
|||||||
const double persistentHeight = 44.0;
|
const double persistentHeight = 44.0;
|
||||||
const double largeTitleHeight = 44.0;
|
const double largeTitleHeight = 44.0;
|
||||||
const double bottomHeight = 10.0;
|
const double bottomHeight = 10.0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -2119,6 +2134,7 @@ void main() {
|
|||||||
) async {
|
) async {
|
||||||
const double bottomHeight = 10.0;
|
const double bottomHeight = 10.0;
|
||||||
const double bottomDisplacement = 96.0;
|
const double bottomDisplacement = 96.0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -2166,6 +2182,7 @@ void main() {
|
|||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
const double largeTitleHeight = 52.0;
|
const double largeTitleHeight = 52.0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -2212,6 +2229,7 @@ void main() {
|
|||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
const double largeTitleHeight = 52.0;
|
const double largeTitleHeight = 52.0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -2258,6 +2276,7 @@ void main() {
|
|||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
const double largeTitleHeight = 52.0;
|
const double largeTitleHeight = 52.0;
|
||||||
const double bottomHeight = 100.0;
|
const double bottomHeight = 100.0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -2323,6 +2342,7 @@ void main() {
|
|||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
const double largeTitleHeight = 52.0;
|
const double largeTitleHeight = 52.0;
|
||||||
const double bottomHeight = 100.0;
|
const double bottomHeight = 100.0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -2392,6 +2412,7 @@ void main() {
|
|||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
const double largeTitleHeight = 52.0;
|
const double largeTitleHeight = 52.0;
|
||||||
const double bottomHeight = 100.0;
|
const double bottomHeight = 100.0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -2459,6 +2480,7 @@ void main() {
|
|||||||
final ScrollController scrollController = ScrollController();
|
final ScrollController scrollController = ScrollController();
|
||||||
addTearDown(scrollController.dispose);
|
addTearDown(scrollController.dispose);
|
||||||
const double largeTitleHeight = 52.0;
|
const double largeTitleHeight = 52.0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
@ -2542,6 +2564,7 @@ void main() {
|
|||||||
testWidgets('CupertinoSliverNavigationBar.search field collapses nav bar on tap', (
|
testWidgets('CupertinoSliverNavigationBar.search field collapses nav bar on tap', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
const CupertinoApp(
|
const CupertinoApp(
|
||||||
home: CustomScrollView(
|
home: CustomScrollView(
|
||||||
@ -2609,8 +2632,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('CupertinoSliverNavigationBar.search golden tests', (WidgetTester tester) async {
|
testWidgets('CupertinoSliverNavigationBar.search golden tests', (WidgetTester tester) async {
|
||||||
await tester.binding.setSurfaceSize(const Size(390, 850));
|
setWindowToPortrait(tester);
|
||||||
addTearDown(() => tester.binding.setSurfaceSize(null));
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
const CupertinoApp(
|
const CupertinoApp(
|
||||||
home: RepaintBoundary(
|
home: RepaintBoundary(
|
||||||
@ -2672,6 +2694,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('onSearchableBottomTap callback', (WidgetTester tester) async {
|
testWidgets('onSearchableBottomTap callback', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
const Color activeSearchColor = Color(0x0000000A);
|
const Color activeSearchColor = Color(0x0000000A);
|
||||||
const Color inactiveSearchColor = Color(0x0000000B);
|
const Color inactiveSearchColor = Color(0x0000000B);
|
||||||
bool isSearchActive = false;
|
bool isSearchActive = false;
|
||||||
@ -2750,6 +2773,7 @@ void main() {
|
|||||||
testWidgets(
|
testWidgets(
|
||||||
'CupertinoSliverNavigationBar.search large title and cancel buttons fade during search animation',
|
'CupertinoSliverNavigationBar.search large title and cancel buttons fade during search animation',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
const CupertinoApp(
|
const CupertinoApp(
|
||||||
home: CustomScrollView(
|
home: CustomScrollView(
|
||||||
@ -2826,6 +2850,52 @@ void main() {
|
|||||||
expect(cancelOpacity.opacity.value, 0.0);
|
expect(cancelOpacity.opacity.value, 0.0);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
testWidgets('Large title is hidden if middle is provided in landscape mode', (
|
||||||
|
WidgetTester tester,
|
||||||
|
) async {
|
||||||
|
const String largeTitle = 'Large title';
|
||||||
|
const String middle = 'Middle';
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const CupertinoApp(
|
||||||
|
home: CustomScrollView(
|
||||||
|
slivers: <Widget>[
|
||||||
|
CupertinoSliverNavigationBar.search(
|
||||||
|
largeTitle: Text(largeTitle),
|
||||||
|
middle: Text(middle),
|
||||||
|
searchField: CupertinoSearchTextField(),
|
||||||
|
),
|
||||||
|
SliverFillRemaining(child: SizedBox(height: 1000.0)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.text(largeTitle), findsNothing);
|
||||||
|
expect(find.text(middle), findsOneWidget);
|
||||||
|
expect(find.byType(CupertinoSearchTextField), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Large title is shown in middle position in landscape mode', (
|
||||||
|
WidgetTester tester,
|
||||||
|
) async {
|
||||||
|
const String largeTitle = 'Large title';
|
||||||
|
await tester.pumpWidget(
|
||||||
|
const CupertinoApp(
|
||||||
|
home: CustomScrollView(
|
||||||
|
slivers: <Widget>[
|
||||||
|
CupertinoSliverNavigationBar.search(
|
||||||
|
largeTitle: Text(largeTitle),
|
||||||
|
searchField: CupertinoSearchTextField(),
|
||||||
|
),
|
||||||
|
SliverFillRemaining(child: SizedBox(height: 1000.0)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(find.text(largeTitle), findsOneWidget);
|
||||||
|
expect(find.byType(CupertinoSearchTextField), findsOneWidget);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ExpectStyles extends StatelessWidget {
|
class _ExpectStyles extends StatelessWidget {
|
||||||
|
@ -132,6 +132,11 @@ void checkOpacity(WidgetTester tester, Finder finder, double opacity) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setWindowToPortrait(WidgetTester tester, {Size size = const Size(2400.0, 3000.0)}) {
|
||||||
|
tester.view.physicalSize = size;
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWidgets('Bottom middle moves between middle and back label', (WidgetTester tester) async {
|
testWidgets('Bottom middle moves between middle and back label', (WidgetTester tester) async {
|
||||||
await startTransitionBetween(tester, fromTitle: 'Page 1');
|
await startTransitionBetween(tester, fromTitle: 'Page 1');
|
||||||
@ -666,6 +671,7 @@ void main() {
|
|||||||
testWidgets('Middle is not shown if alwaysShowMiddle is false and the nav bar is expanded', (
|
testWidgets('Middle is not shown if alwaysShowMiddle is false and the nav bar is expanded', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
const Widget userMiddle = Placeholder();
|
const Widget userMiddle = Placeholder();
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
@ -987,6 +993,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Bottom large title moves to top back label', (WidgetTester tester) async {
|
testWidgets('Bottom large title moves to top back label', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
from: const CupertinoSliverNavigationBar(),
|
from: const CupertinoSliverNavigationBar(),
|
||||||
@ -1045,6 +1052,7 @@ void main() {
|
|||||||
testWidgets('Bottom CupertinoSliverNavigationBar.bottom fades and slides out from the left', (
|
testWidgets('Bottom CupertinoSliverNavigationBar.bottom fades and slides out from the left', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
from: const CupertinoSliverNavigationBar(
|
from: const CupertinoSliverNavigationBar(
|
||||||
@ -1081,6 +1089,7 @@ void main() {
|
|||||||
testWidgets('Bottom CupertinoNavigationBar.bottom fades and slides out from the left', (
|
testWidgets('Bottom CupertinoNavigationBar.bottom fades and slides out from the left', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
from: const CupertinoNavigationBar(
|
from: const CupertinoNavigationBar(
|
||||||
@ -1117,6 +1126,7 @@ void main() {
|
|||||||
testWidgets(
|
testWidgets(
|
||||||
'CupertinoSliverNavigationBar.bottom clips its contents mid-transition when scrolled',
|
'CupertinoSliverNavigationBar.bottom clips its contents mid-transition when scrolled',
|
||||||
(WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
CupertinoApp(
|
CupertinoApp(
|
||||||
builder: (BuildContext context, Widget? navigator) {
|
builder: (BuildContext context, Widget? navigator) {
|
||||||
@ -1233,6 +1243,7 @@ void main() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
testWidgets('Long title turns into the word back mid transition', (WidgetTester tester) async {
|
testWidgets('Long title turns into the word back mid transition', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
from: const CupertinoSliverNavigationBar(),
|
from: const CupertinoSliverNavigationBar(),
|
||||||
@ -1289,6 +1300,7 @@ void main() {
|
|||||||
testWidgets('Bottom large title and top back label transitions their font', (
|
testWidgets('Bottom large title and top back label transitions their font', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
from: const CupertinoSliverNavigationBar(),
|
from: const CupertinoSliverNavigationBar(),
|
||||||
@ -1397,6 +1409,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Top large title fades in and slides in from the right', (WidgetTester tester) async {
|
testWidgets('Top large title fades in and slides in from the right', (WidgetTester tester) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
to: const CupertinoSliverNavigationBar(),
|
to: const CupertinoSliverNavigationBar(),
|
||||||
@ -1427,6 +1440,7 @@ void main() {
|
|||||||
testWidgets('Top large title fades in and slides in from the left in RTL', (
|
testWidgets('Top large title fades in and slides in from the left in RTL', (
|
||||||
WidgetTester tester,
|
WidgetTester tester,
|
||||||
) async {
|
) async {
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
to: const CupertinoSliverNavigationBar(),
|
to: const CupertinoSliverNavigationBar(),
|
||||||
@ -1460,6 +1474,7 @@ void main() {
|
|||||||
) async {
|
) async {
|
||||||
const double horizontalPadding = 16.0; // _kNavBarEdgePadding
|
const double horizontalPadding = 16.0; // _kNavBarEdgePadding
|
||||||
const double height = 30.0;
|
const double height = 30.0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
toTitle: 'Page 2',
|
toTitle: 'Page 2',
|
||||||
@ -1503,7 +1518,7 @@ void main() {
|
|||||||
// The nav bar bottom is horizontally aligned to the large title.
|
// The nav bar bottom is horizontally aligned to the large title.
|
||||||
expect(
|
expect(
|
||||||
tester.getTopLeft(flying(tester, find.byType(Placeholder))).dx,
|
tester.getTopLeft(flying(tester, find.byType(Placeholder))).dx,
|
||||||
largeTitleOffset.dx - horizontalPadding,
|
moreOrLessEquals(largeTitleOffset.dx - horizontalPadding, epsilon: 0.01),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -1581,6 +1596,7 @@ void main() {
|
|||||||
) async {
|
) async {
|
||||||
int bottomBuildTimes = 0;
|
int bottomBuildTimes = 0;
|
||||||
int topBuildTimes = 0;
|
int topBuildTimes = 0;
|
||||||
|
setWindowToPortrait(tester);
|
||||||
await startTransitionBetween(
|
await startTransitionBetween(
|
||||||
tester,
|
tester,
|
||||||
from: CupertinoNavigationBar(
|
from: CupertinoNavigationBar(
|
||||||
|
@ -51,6 +51,9 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Large title auto-populates with title', (WidgetTester tester) async {
|
testWidgets('Large title auto-populates with title', (WidgetTester tester) async {
|
||||||
|
// Set window orientation to portrait.
|
||||||
|
tester.view.physicalSize = const Size(2400.0, 3000.0);
|
||||||
|
addTearDown(tester.view.reset);
|
||||||
await tester.pumpWidget(const CupertinoApp(home: Placeholder()));
|
await tester.pumpWidget(const CupertinoApp(home: Placeholder()));
|
||||||
|
|
||||||
tester
|
tester
|
||||||
|
Loading…
Reference in New Issue
Block a user