Add padding for Navigation Bar to account for safe area (#102419)
This commit is contained in:
parent
4cea9afc12
commit
57a688c1f0
@ -147,41 +147,35 @@ class NavigationBar extends StatelessWidget {
|
||||
final NavigationDestinationLabelBehavior effectiveLabelBehavior = labelBehavior
|
||||
?? navigationBarTheme.labelBehavior
|
||||
?? defaults.labelBehavior!;
|
||||
final double additionalBottomPadding = MediaQuery.of(context).padding.bottom;
|
||||
|
||||
return Material(
|
||||
color: backgroundColor
|
||||
?? navigationBarTheme.backgroundColor
|
||||
?? defaults.backgroundColor!,
|
||||
elevation: elevation ?? navigationBarTheme.elevation ?? defaults.elevation!,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(bottom: additionalBottomPadding),
|
||||
child: MediaQuery.removePadding(
|
||||
context: context,
|
||||
removeBottom: true,
|
||||
child: SizedBox(
|
||||
height: effectiveHeight,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
for (int i = 0; i < destinations.length; i++)
|
||||
Expanded(
|
||||
child: _SelectableAnimatedBuilder(
|
||||
duration: animationDuration ?? const Duration(milliseconds: 500),
|
||||
isSelected: i == selectedIndex,
|
||||
builder: (BuildContext context, Animation<double> animation) {
|
||||
return _NavigationDestinationInfo(
|
||||
index: i,
|
||||
totalNumberOfDestinations: destinations.length,
|
||||
selectedAnimation: animation,
|
||||
labelBehavior: effectiveLabelBehavior,
|
||||
onTap: _handleTap(i),
|
||||
child: destinations[i],
|
||||
);
|
||||
},
|
||||
),
|
||||
child: SafeArea(
|
||||
child: SizedBox(
|
||||
height: effectiveHeight,
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
for (int i = 0; i < destinations.length; i++)
|
||||
Expanded(
|
||||
child: _SelectableAnimatedBuilder(
|
||||
duration: animationDuration ?? const Duration(milliseconds: 500),
|
||||
isSelected: i == selectedIndex,
|
||||
builder: (BuildContext context, Animation<double> animation) {
|
||||
return _NavigationDestinationInfo(
|
||||
index: i,
|
||||
totalNumberOfDestinations: destinations.length,
|
||||
selectedAnimation: animation,
|
||||
labelBehavior: effectiveLabelBehavior,
|
||||
onTap: _handleTap(i),
|
||||
child: destinations[i],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
@ -137,6 +138,104 @@ void main() {
|
||||
expect(tester.getSize(find.byType(NavigationBar)).height, expectedHeight);
|
||||
});
|
||||
|
||||
testWidgets('NavigationBar respects the notch/system navigation bar in landscape mode', (WidgetTester tester) async {
|
||||
const double safeAreaPadding = 40.0;
|
||||
Widget navigationBar() {
|
||||
return NavigationBar(
|
||||
destinations: const <Widget>[
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.ac_unit),
|
||||
label: 'AC',
|
||||
),
|
||||
NavigationDestination(
|
||||
key: Key('Center'),
|
||||
icon: Icon(Icons.center_focus_strong),
|
||||
label: 'Center',
|
||||
),
|
||||
NavigationDestination(
|
||||
icon: Icon(Icons.access_alarm),
|
||||
label: 'Alarm',
|
||||
),
|
||||
],
|
||||
onDestinationSelected: (int i) {},
|
||||
);
|
||||
}
|
||||
|
||||
await tester.pumpWidget(_buildWidget(navigationBar()));
|
||||
final double defaultWidth = tester.getSize(find.byType(NavigationBar)).width;
|
||||
final Finder defaultCenterItem = find.byKey(const Key('Center'));
|
||||
final Offset center = tester.getCenter(defaultCenterItem);
|
||||
expect(center.dx, defaultWidth / 2);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_buildWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: EdgeInsets.only(left: safeAreaPadding),
|
||||
),
|
||||
child: navigationBar(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// The position of center item of navigation bar should indicate whether
|
||||
// the safe area is sufficiently respected, when safe area is on the left side.
|
||||
// e.g. Android device with system navigation bar in landscape mode.
|
||||
final Finder leftPaddedCenterItem = find.byKey(const Key('Center'));
|
||||
final Offset leftPaddedCenter = tester.getCenter(leftPaddedCenterItem);
|
||||
expect(
|
||||
leftPaddedCenter.dx,
|
||||
closeTo((defaultWidth + safeAreaPadding) / 2.0, precisionErrorTolerance),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_buildWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: EdgeInsets.only(right: safeAreaPadding)
|
||||
),
|
||||
child: navigationBar(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// The position of center item of navigation bar should indicate whether
|
||||
// the safe area is sufficiently respected, when safe area is on the right side.
|
||||
// e.g. Android device with system navigation bar in landscape mode.
|
||||
final Finder rightPaddedCenterItem = find.byKey(const Key('Center'));
|
||||
final Offset rightPaddedCenter = tester.getCenter(rightPaddedCenterItem);
|
||||
expect(
|
||||
rightPaddedCenter.dx,
|
||||
closeTo((defaultWidth - safeAreaPadding) / 2, precisionErrorTolerance),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(
|
||||
_buildWidget(
|
||||
MediaQuery(
|
||||
data: const MediaQueryData(
|
||||
padding: EdgeInsets.fromLTRB(
|
||||
safeAreaPadding,
|
||||
0,
|
||||
safeAreaPadding,
|
||||
safeAreaPadding
|
||||
),
|
||||
),
|
||||
child: navigationBar(),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// The position of center item of navigation bar should indicate whether
|
||||
// the safe area is sufficiently respected, when safe areas are on both sides.
|
||||
// e.g. iOS device with both sides of round corner.
|
||||
final Finder paddedCenterItem = find.byKey(const Key('Center'));
|
||||
final Offset paddedCenter = tester.getCenter(paddedCenterItem);
|
||||
expect(
|
||||
paddedCenter.dx,
|
||||
closeTo(defaultWidth / 2, precisionErrorTolerance),
|
||||
);
|
||||
});
|
||||
|
||||
testWidgets('NavigationBar uses proper defaults when no parameters are given', (WidgetTester tester) async {
|
||||
// Pre-M3 settings that were hand coded.
|
||||
await tester.pumpWidget(
|
||||
|
Loading…
x
Reference in New Issue
Block a user