Put the nav bar padding inside the CustomMultiChildLayout for correct centering and allow custom padding (#19129)

This commit is contained in:
xster 2018-07-09 12:27:24 -07:00 committed by GitHub
parent 5c8d7e3421
commit e08177155e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 174 additions and 23 deletions

View File

@ -26,9 +26,6 @@ const double _kNavBarShowLargeTitleThreshold = 10.0;
const double _kNavBarEdgePadding = 16.0;
// The back chevron has a special padding in iOS.
const double _kNavBarBackButtonPadding = 0.0;
const double _kNavBarBackButtonTapWidth = 50.0;
/// Title text transfer fade.
@ -87,6 +84,7 @@ class CupertinoNavigationBar extends StatelessWidget implements ObstructingPrefe
this.trailing,
this.border = _kDefaultNavBarBorder,
this.backgroundColor = _kDefaultNavBarBackgroundColor,
this.padding,
this.actionsForegroundColor = CupertinoColors.activeBlue,
}) : assert(automaticallyImplyLeading != null),
super(key: key);
@ -118,6 +116,19 @@ class CupertinoNavigationBar extends StatelessWidget implements ObstructingPrefe
/// behind it.
final Color backgroundColor;
/// Padding for the contents of the navigation bar.
///
/// If null, the navigation bar will adopt the following defaults:
///
/// * Vertically, contents will be sized to the same height as the navigation
/// bar itself minus the status bar.
/// * Horizontally, padding will be 16 pixels according to iOS specifications
/// unless the leading widget is an automatically inserted back button, in
/// which case the padding will be 0.
///
/// Vertical padding won't change the height of the nav bar.
final EdgeInsetsDirectional padding;
/// The border of the navigation bar. By default renders a single pixel bottom border side.
///
/// If a border is null, the navigation bar will not display a border.
@ -149,6 +160,7 @@ class CupertinoNavigationBar extends StatelessWidget implements ObstructingPrefe
automaticallyImplyLeading: automaticallyImplyLeading,
middle: new Semantics(child: middle, header: true),
trailing: trailing,
padding: padding,
actionsForegroundColor: actionsForegroundColor,
),
);
@ -197,6 +209,7 @@ class CupertinoSliverNavigationBar extends StatelessWidget {
this.trailing,
this.border = _kDefaultNavBarBorder,
this.backgroundColor = _kDefaultNavBarBackgroundColor,
this.padding,
this.actionsForegroundColor = CupertinoColors.activeBlue,
}) : assert(largeTitle != null),
assert(automaticallyImplyLeading != null),
@ -246,6 +259,19 @@ class CupertinoSliverNavigationBar extends StatelessWidget {
/// This widget is visible in both collapsed and expanded states.
final Widget trailing;
/// Padding for the contents of the navigation bar.
///
/// If null, the navigation bar will adopt the following defaults:
///
/// * Vertically, contents will be sized to the same height as the navigation
/// bar itself minus the status bar.
/// * Horizontally, padding will be 16 pixels according to iOS specifications
/// unless the leading widget is an automatically inserted back button, in
/// which case the padding will be 0.
///
/// Vertical padding won't change the height of the nav bar.
final EdgeInsetsDirectional padding;
/// The border of the navigation bar. By default renders a single pixel bottom border side.
///
/// If a border is null, the navigation bar will not display a border.
@ -277,6 +303,7 @@ class CupertinoSliverNavigationBar extends StatelessWidget {
automaticallyImplyLeading: automaticallyImplyLeading,
middle: middle,
trailing: trailing,
padding: padding,
border: border,
backgroundColor: backgroundColor,
actionsForegroundColor: actionsForegroundColor,
@ -332,6 +359,7 @@ class _CupertinoPersistentNavigationBar extends StatelessWidget implements Prefe
this.automaticallyImplyLeading,
this.middle,
this.trailing,
this.padding,
this.actionsForegroundColor,
this.middleVisible,
}) : super(key: key);
@ -344,6 +372,8 @@ class _CupertinoPersistentNavigationBar extends StatelessWidget implements Prefe
final Widget trailing;
final EdgeInsetsDirectional padding;
final Color actionsForegroundColor;
/// Whether the middle widget has a visible animated opacity. A null value
@ -362,15 +392,29 @@ class _CupertinoPersistentNavigationBar extends StatelessWidget implements Prefe
color: actionsForegroundColor,
);
final Widget styledLeading = leading == null ? null : new DefaultTextStyle(
style: actionsStyle,
child: leading,
);
final Widget styledLeading = leading == null
? null
: new Padding(
padding: new EdgeInsetsDirectional.only(
start: padding?.start ?? _kNavBarEdgePadding,
),
child: new DefaultTextStyle(
style: actionsStyle,
child: leading,
),
);
final Widget styledTrailing = trailing == null ? null : new DefaultTextStyle(
style: actionsStyle,
child: trailing,
);
final Widget styledTrailing = trailing == null
? null
: Padding(
padding: new EdgeInsetsDirectional.only(
end: padding?.end ?? _kNavBarEdgePadding,
),
child: new DefaultTextStyle(
style: actionsStyle,
child: trailing,
),
);
// Let the middle be black rather than `actionsForegroundColor` in case
// it's a plain text title.
@ -413,6 +457,23 @@ class _CupertinoPersistentNavigationBar extends StatelessWidget implements Prefe
}
}
Widget paddedToolbar = new NavigationToolbar(
leading: styledLeading ?? backOrCloseButton,
middle: animatedStyledMiddle,
trailing: styledTrailing,
centerMiddle: true,
);
if (padding != null) {
paddedToolbar = new Padding(
padding: EdgeInsets.only(
top: padding.top,
bottom: padding.bottom,
),
child: paddedToolbar,
);
}
return new SizedBox(
height: _kNavBarPersistentHeight + MediaQuery.of(context).padding.top,
child: IconTheme.merge(
@ -422,18 +483,7 @@ class _CupertinoPersistentNavigationBar extends StatelessWidget implements Prefe
),
child: new SafeArea(
bottom: false,
child: new Padding(
padding: new EdgeInsetsDirectional.only(
start: useBackButton ? _kNavBarBackButtonPadding : _kNavBarEdgePadding,
end: _kNavBarEdgePadding,
),
child: new NavigationToolbar(
leading: styledLeading ?? backOrCloseButton,
middle: animatedStyledMiddle,
trailing: styledTrailing,
centerMiddle: true,
),
),
child: paddedToolbar,
),
),
);
@ -449,6 +499,7 @@ class _CupertinoLargeTitleNavigationBarSliverDelegate
this.automaticallyImplyLeading,
this.middle,
this.trailing,
this.padding,
this.border,
this.backgroundColor,
this.actionsForegroundColor,
@ -466,6 +517,8 @@ class _CupertinoLargeTitleNavigationBarSliverDelegate
final Widget trailing;
final EdgeInsetsDirectional padding;
final Color backgroundColor;
final Border border;
@ -491,6 +544,7 @@ class _CupertinoLargeTitleNavigationBarSliverDelegate
// If middle widget exists, always show it. Otherwise, show title
// when collapsed.
middleVisible: middle != null ? null : !showLargeTitle,
padding: padding,
actionsForegroundColor: actionsForegroundColor,
);

View File

@ -28,6 +28,30 @@ void main() {
expect(tester.getCenter(find.text('Title')).dx, 400.0);
});
testWidgets('Middle still in center with back button', (WidgetTester tester) async {
await tester.pumpWidget(
new CupertinoApp(
home: const CupertinoNavigationBar(
middle: const Text('Title'),
),
),
);
tester.state<NavigatorState>(find.byType(Navigator)).push(new CupertinoPageRoute<void>(
builder: (BuildContext context) {
return const CupertinoNavigationBar(
middle: const Text('Page 2'),
);
},
));
await tester.pump();
await tester.pump(const Duration(milliseconds: 500));
// Expect the middle of the title to be exactly in the middle of the screen.
expect(tester.getCenter(find.text('Page 2')).dx, 400.0);
});
testWidgets('Opaque background does not add blur effects', (WidgetTester tester) async {
await tester.pumpWidget(
new CupertinoApp(
@ -51,6 +75,79 @@ void main() {
expect(find.byType(BackdropFilter), findsOneWidget);
});
testWidgets('Can specify custom padding', (WidgetTester tester) async {
final Key middleBox = new GlobalKey();
await tester.pumpWidget(
new CupertinoApp(
home: new Align(
alignment: Alignment.topCenter,
child: new CupertinoNavigationBar(
leading: const CupertinoButton(child: const Text('Cheetah'), onPressed: null),
// Let the box take all the vertical space to test vertical padding but let
// the nav bar position it horizontally.
middle: new Align(
key: middleBox,
alignment: Alignment.center,
widthFactor: 1.0,
child: const Text('Title')
),
trailing: const CupertinoButton(child: const Text('Puma'), onPressed: null),
padding: const EdgeInsetsDirectional.only(
start: 10.0,
end: 20.0,
top: 3.0,
bottom: 4.0,
),
),
),
),
);
expect(tester.getRect(find.byKey(middleBox)).top, 3.0);
// 44 is the standard height of the nav bar.
expect(
tester.getRect(find.byKey(middleBox)).bottom,
// 44 is the standard height of the nav bar.
44.0 - 4.0,
);
expect(tester.getTopLeft(find.widgetWithText(CupertinoButton, 'Cheetah')).dx, 10.0);
expect(tester.getTopRight(find.widgetWithText(CupertinoButton, 'Puma')).dx, 800.0 - 20.0);
// Title is still exactly centered.
expect(tester.getCenter(find.text('Title')).dx, 400.0);
});
testWidgets('Padding works in RTL', (WidgetTester tester) async {
await tester.pumpWidget(
new CupertinoApp(
home: const Directionality(
textDirection: TextDirection.rtl,
child: const Align(
alignment: Alignment.topCenter,
child: const CupertinoNavigationBar(
leading: const CupertinoButton(child: const Text('Cheetah'), onPressed: null),
// Let the box take all the vertical space to test vertical padding but let
// the nav bar position it horizontally.
middle: const Text('Title'),
trailing: const CupertinoButton(child: const Text('Puma'), onPressed: null),
padding: const EdgeInsetsDirectional.only(
start: 10.0,
end: 20.0,
),
),
),
),
),
);
expect(tester.getTopRight(find.widgetWithText(CupertinoButton, 'Cheetah')).dx, 800.0 - 10.0);
expect(tester.getTopLeft(find.widgetWithText(CupertinoButton, 'Puma')).dx, 20.0);
// Title is still exactly centered.
expect(tester.getCenter(find.text('Title')).dx, 400.0);
});
testWidgets('Verify styles of each slot', (WidgetTester tester) async {
count = 0x000000;
await tester.pumpWidget(