Unverified Commit 2b621e1a authored by Qun Cheng's avatar Qun Cheng Committed by GitHub

Add SafeArea for NavigationRail (#107605)

* Added SafeArea for NavigationRail
Co-authored-by: 's avatarQun Cheng <quncheng@google.com>
parent 7976287e
......@@ -402,6 +402,8 @@ class _NavigationRailState extends State<NavigationRail> with TickerProviderStat
? unselectedIconTheme
: unselectedIconTheme.copyWith(opacity: unselectedIconTheme.opacity ?? defaults.unselectedIconTheme!.opacity);
final bool isRTLDirection = Directionality.of(context) == TextDirection.rtl;
return _ExtendedNavigationRailAnimation(
animation: _extendedAnimation,
child: Semantics(
......@@ -409,52 +411,56 @@ class _NavigationRailState extends State<NavigationRail> with TickerProviderStat
child: Material(
elevation: elevation,
color: backgroundColor,
child: Column(
children: <Widget>[
_verticalSpacer,
if (widget.leading != null)
...<Widget>[
widget.leading!,
_verticalSpacer,
],
Expanded(
child: Align(
alignment: Alignment(0, groupAlignment),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
for (int i = 0; i < widget.destinations.length; i += 1)
_RailDestination(
minWidth: minWidth,
minExtendedWidth: minExtendedWidth,
extendedTransitionAnimation: _extendedAnimation,
selected: widget.selectedIndex == i,
icon: widget.selectedIndex == i ? widget.destinations[i].selectedIcon : widget.destinations[i].icon,
label: widget.destinations[i].label,
destinationAnimation: _destinationAnimations[i],
labelType: labelType,
iconTheme: widget.selectedIndex == i ? selectedIconTheme : effectiveUnselectedIconTheme,
labelTextStyle: widget.selectedIndex == i ? selectedLabelTextStyle : unselectedLabelTextStyle,
padding: widget.destinations[i].padding,
useIndicator: useIndicator,
indicatorColor: useIndicator ? indicatorColor : null,
onTap: () {
if (widget.onDestinationSelected != null) {
widget.onDestinationSelected!(i);
}
},
indexLabel: localizations.tabLabel(
tabIndex: i + 1,
tabCount: widget.destinations.length,
child: SafeArea(
right: isRTLDirection,
left: !isRTLDirection,
child: Column(
children: <Widget>[
_verticalSpacer,
if (widget.leading != null)
...<Widget>[
widget.leading!,
_verticalSpacer,
],
Expanded(
child: Align(
alignment: Alignment(0, groupAlignment),
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
for (int i = 0; i < widget.destinations.length; i += 1)
_RailDestination(
minWidth: minWidth,
minExtendedWidth: minExtendedWidth,
extendedTransitionAnimation: _extendedAnimation,
selected: widget.selectedIndex == i,
icon: widget.selectedIndex == i ? widget.destinations[i].selectedIcon : widget.destinations[i].icon,
label: widget.destinations[i].label,
destinationAnimation: _destinationAnimations[i],
labelType: labelType,
iconTheme: widget.selectedIndex == i ? selectedIconTheme : effectiveUnselectedIconTheme,
labelTextStyle: widget.selectedIndex == i ? selectedLabelTextStyle : unselectedLabelTextStyle,
padding: widget.destinations[i].padding,
useIndicator: useIndicator,
indicatorColor: useIndicator ? indicatorColor : null,
onTap: () {
if (widget.onDestinationSelected != null) {
widget.onDestinationSelected!(i);
}
},
indexLabel: localizations.tabLabel(
tabIndex: i + 1,
tabCount: widget.destinations.length,
),
),
),
if (widget.trailing != null)
widget.trailing!,
],
if (widget.trailing != null)
widget.trailing!,
],
),
),
),
),
],
],
),
),
),
),
......
......@@ -2314,9 +2314,15 @@ void main() {
),
);
final Padding firstItem = tester.widget<Padding>(find.widgetWithText(Padding, 'Abc'));
final Padding secondItem = tester.widget<Padding>(find.widgetWithText(Padding, 'Def'));
final Padding thirdItem = tester.widget<Padding>(find.widgetWithText(Padding, 'Ghi'));
final Padding firstItem = tester.widget<Padding>(
find.descendant(of: find.widgetWithText(InkResponse, 'Abc'), matching: find.widgetWithText(Padding, 'Abc'))
);
final Padding secondItem = tester.widget<Padding>(
find.descendant(of: find.widgetWithText(InkResponse, 'Def'), matching: find.widgetWithText(Padding, 'Def'))
);
final Padding thirdItem = tester.widget<Padding>(
find.descendant(of: find.widgetWithText(InkResponse, 'Ghi'), matching: find.widgetWithText(Padding, 'Ghi'))
);
expect(firstItem.padding, defaultPadding);
expect(secondItem.padding, secondItemPadding);
......@@ -2355,9 +2361,15 @@ void main() {
),
);
final Padding firstItem = tester.widget<Padding>(find.widgetWithText(Padding, 'Abc'));
final Padding secondItem = tester.widget<Padding>(find.widgetWithText(Padding, 'Def'));
final Padding thirdItem = tester.widget<Padding>(find.widgetWithText(Padding, 'Ghi'));
final Padding firstItem = tester.widget<Padding>(
find.descendant(of: find.widgetWithText(InkResponse, 'Abc'), matching: find.widgetWithText(Padding, 'Abc'))
);
final Padding secondItem = tester.widget<Padding>(
find.descendant(of: find.widgetWithText(InkResponse, 'Def'), matching: find.widgetWithText(Padding, 'Def'))
);
final Padding thirdItem = tester.widget<Padding>(
find.descendant(of: find.widgetWithText(InkResponse, 'Ghi'), matching: find.widgetWithText(Padding, 'Ghi'))
);
expect(firstItem.padding, defaultPadding);
expect(secondItem.padding, secondItemPadding);
......@@ -2396,9 +2408,15 @@ void main() {
),
);
final Padding firstItem = tester.widget<Padding>(find.widgetWithText(Padding, 'Abc'));
final Padding secondItem = tester.widget<Padding>(find.widgetWithText(Padding, 'Def'));
final Padding thirdItem = tester.widget<Padding>(find.widgetWithText(Padding, 'Ghi'));
final Padding firstItem = tester.widget<Padding>(
find.descendant(of: find.widgetWithText(InkResponse, 'Abc'), matching: find.widgetWithText(Padding, 'Abc'))
);
final Padding secondItem = tester.widget<Padding>(
find.descendant(of: find.widgetWithText(InkResponse, 'Def'), matching: find.widgetWithText(Padding, 'Def'))
);
final Padding thirdItem = tester.widget<Padding>(
find.descendant(of: find.widgetWithText(InkResponse, 'Ghi'), matching: find.widgetWithText(Padding, 'Ghi'))
);
expect(firstItem.padding, defaultPadding);
expect(secondItem.padding, secondItemPadding);
......@@ -2637,6 +2655,59 @@ void main() {
expect(lastIndicator.localToGlobal(Offset.zero).dx, 28.0);
});
testWidgets('NavigationRail respects the notch/system navigation bar in landscape mode', (WidgetTester tester) async {
const double safeAreaPadding = 40.0;
NavigationRail navigationRail() {
return NavigationRail(
selectedIndex: 0,
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('Abc'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.bookmark),
label: Text('Def'),
),
],
);
}
await tester.pumpWidget(_buildWidget(navigationRail()));
final double defaultWidth = tester.getSize(find.byType(NavigationRail)).width;
expect(defaultWidth, 80);
await tester.pumpWidget(
_buildWidget(
MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(left: safeAreaPadding),
),
child: navigationRail(),
),
),
);
final double updatedWidth = tester.getSize(find.byType(NavigationRail)).width;
expect(updatedWidth, defaultWidth + safeAreaPadding);
// test width when text direction is RTL.
await tester.pumpWidget(
_buildWidget(
MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(right: safeAreaPadding),
),
child: navigationRail(),
),
isRTL: true,
),
);
final double updatedWidthRTL = tester.getSize(find.byType(NavigationRail)).width;
expect(updatedWidthRTL, defaultWidth + safeAreaPadding);
});
group('Material 2', () {
// Original Material 2 tests. Remove this group after `useMaterial3` has been deprecated.
testWidgets('Renders at the correct default width - [labelType]=none (default)', (WidgetTester tester) async {
......@@ -4392,6 +4463,61 @@ void main() {
expect(lastIndicator.localToGlobal(Offset.zero).dx, 24.0);
});
testWidgets('NavigationRail respects the notch/system navigation bar in landscape mode', (WidgetTester tester) async {
const double safeAreaPadding = 40.0;
NavigationRail navigationRail() {
return NavigationRail(
selectedIndex: 0,
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('Abc'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.bookmark),
label: Text('Def'),
),
],
);
}
await tester.pumpWidget(_buildWidget(navigationRail(), useMaterial3: false));
final double defaultWidth = tester.getSize(find.byType(NavigationRail)).width;
expect(defaultWidth, 72);
await tester.pumpWidget(
_buildWidget(
MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(left: safeAreaPadding),
),
child: navigationRail(),
),
useMaterial3: false
),
);
final double updatedWidth = tester.getSize(find.byType(NavigationRail)).width;
expect(updatedWidth, defaultWidth + safeAreaPadding);
// test width when text direction is RTL.
await tester.pumpWidget(
_buildWidget(
MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.only(right: safeAreaPadding),
),
child: navigationRail(),
),
useMaterial3: false,
isRTL: true,
),
);
final double updatedWidthRTL = tester.getSize(find.byType(NavigationRail)).width;
expect(updatedWidthRTL, defaultWidth + safeAreaPadding);
});
}); // End Material 2 group
}
......@@ -4595,3 +4721,22 @@ Material _railMaterial(WidgetTester tester) {
),
);
}
Widget _buildWidget(Widget child, {bool useMaterial3 = true, bool isRTL = false}) {
return MaterialApp(
theme: ThemeData(useMaterial3: useMaterial3),
home: Directionality(
textDirection: isRTL ? TextDirection.rtl : TextDirection.ltr,
child: Scaffold(
body: Row(
children: <Widget>[
child,
const Expanded(
child: Text('body'),
),
],
),
),
),
);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment