Unverified Commit 26c30fe2 authored by Hans Muller's avatar Hans Muller Committed by GitHub

Added BottomNavigationBar landscapeLayout parameter (#87211)

parent c5866c5e
...@@ -44,6 +44,7 @@ class BottomNavigationBarThemeData with Diagnosticable { ...@@ -44,6 +44,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
this.showUnselectedLabels, this.showUnselectedLabels,
this.type, this.type,
this.enableFeedback, this.enableFeedback,
this.landscapeLayout,
}); });
/// The color of the [BottomNavigationBar] itself. /// The color of the [BottomNavigationBar] itself.
...@@ -120,6 +121,9 @@ class BottomNavigationBarThemeData with Diagnosticable { ...@@ -120,6 +121,9 @@ class BottomNavigationBarThemeData with Diagnosticable {
/// If [BottomNavigationBar.enableFeedback] is provided, [enableFeedback] is ignored. /// If [BottomNavigationBar.enableFeedback] is provided, [enableFeedback] is ignored.
final bool? enableFeedback; final bool? enableFeedback;
/// If non-null, overrides the [BottomNavigationBar.landscapeLayout] property.
final BottomNavigationBarLandscapeLayout? landscapeLayout;
/// Creates a copy of this object but with the given fields replaced with the /// Creates a copy of this object but with the given fields replaced with the
/// new values. /// new values.
BottomNavigationBarThemeData copyWith({ BottomNavigationBarThemeData copyWith({
...@@ -135,6 +139,7 @@ class BottomNavigationBarThemeData with Diagnosticable { ...@@ -135,6 +139,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
bool? showUnselectedLabels, bool? showUnselectedLabels,
BottomNavigationBarType? type, BottomNavigationBarType? type,
bool? enableFeedback, bool? enableFeedback,
BottomNavigationBarLandscapeLayout? landscapeLayout
}) { }) {
return BottomNavigationBarThemeData( return BottomNavigationBarThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor, backgroundColor: backgroundColor ?? this.backgroundColor,
...@@ -149,6 +154,7 @@ class BottomNavigationBarThemeData with Diagnosticable { ...@@ -149,6 +154,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
showUnselectedLabels: showUnselectedLabels ?? this.showUnselectedLabels, showUnselectedLabels: showUnselectedLabels ?? this.showUnselectedLabels,
type: type ?? this.type, type: type ?? this.type,
enableFeedback: enableFeedback ?? this.enableFeedback, enableFeedback: enableFeedback ?? this.enableFeedback,
landscapeLayout: landscapeLayout ?? this.landscapeLayout,
); );
} }
...@@ -172,6 +178,7 @@ class BottomNavigationBarThemeData with Diagnosticable { ...@@ -172,6 +178,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
showUnselectedLabels: t < 0.5 ? a?.showUnselectedLabels : b?.showUnselectedLabels, showUnselectedLabels: t < 0.5 ? a?.showUnselectedLabels : b?.showUnselectedLabels,
type: t < 0.5 ? a?.type : b?.type, type: t < 0.5 ? a?.type : b?.type,
enableFeedback: t < 0.5 ? a?.enableFeedback : b?.enableFeedback, enableFeedback: t < 0.5 ? a?.enableFeedback : b?.enableFeedback,
landscapeLayout: t < 0.5 ? a?.landscapeLayout : b?.landscapeLayout,
); );
} }
...@@ -190,6 +197,7 @@ class BottomNavigationBarThemeData with Diagnosticable { ...@@ -190,6 +197,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
showUnselectedLabels, showUnselectedLabels,
type, type,
enableFeedback, enableFeedback,
landscapeLayout,
); );
} }
...@@ -211,7 +219,8 @@ class BottomNavigationBarThemeData with Diagnosticable { ...@@ -211,7 +219,8 @@ class BottomNavigationBarThemeData with Diagnosticable {
&& other.showSelectedLabels == showSelectedLabels && other.showSelectedLabels == showSelectedLabels
&& other.showUnselectedLabels == showUnselectedLabels && other.showUnselectedLabels == showUnselectedLabels
&& other.type == type && other.type == type
&& other.enableFeedback == enableFeedback; && other.enableFeedback == enableFeedback
&& other.landscapeLayout == landscapeLayout;
} }
@override @override
...@@ -229,6 +238,7 @@ class BottomNavigationBarThemeData with Diagnosticable { ...@@ -229,6 +238,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<bool>('showUnselectedLabels', showUnselectedLabels, defaultValue: null)); properties.add(DiagnosticsProperty<bool>('showUnselectedLabels', showUnselectedLabels, defaultValue: null));
properties.add(DiagnosticsProperty<BottomNavigationBarType>('type', type, defaultValue: null)); properties.add(DiagnosticsProperty<BottomNavigationBarType>('type', type, defaultValue: null));
properties.add(DiagnosticsProperty<bool>('enableFeedback', enableFeedback, defaultValue: null)); properties.add(DiagnosticsProperty<bool>('enableFeedback', enableFeedback, defaultValue: null));
properties.add(DiagnosticsProperty<BottomNavigationBarLandscapeLayout>('landscapeLayout', landscapeLayout, defaultValue: null));
} }
} }
......
...@@ -2015,6 +2015,143 @@ void main() { ...@@ -2015,6 +2015,143 @@ void main() {
semantics.dispose(); semantics.dispose();
}); });
testWidgets('BottomNavigationBar default layout', (WidgetTester tester) async {
final Key icon0 = UniqueKey();
final Key title0 = UniqueKey();
final Key icon1 = UniqueKey();
final Key title1 = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: Builder(
builder: (BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
currentIndex: 0,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: SizedBox(key: icon0, width: 200, height: 10),
title: SizedBox(key: title0, width: 200, height: 10),
),
BottomNavigationBarItem(
icon: SizedBox(key: icon1, width: 200, height: 10),
title: SizedBox(key: title1, width: 200, height: 10),
),
],
),
);
},
),
),
);
expect(tester.getSize(find.byType(BottomNavigationBar)), const Size(800, kBottomNavigationBarHeight));
expect(tester.getRect(find.byType(BottomNavigationBar)), const Rect.fromLTRB(0, 600 - kBottomNavigationBarHeight, 800, 600));
// The height of the navigation bar is kBottomNavigationBarHeight = 56
// The top of the navigation bar is 600 - 56 = 544
// The top and bottom of the selected item is defined by its centered icon/label column:
// top = 544 - (56 - (10 + 10)) / 2 = 562
// bottom = top + 10 + 10 = 582
expect(tester.getRect(find.byKey(icon0)).top, 562);
expect(tester.getRect(find.byKey(title0)).bottom, 582);
// The items are horizontal padded according to
// MainAxisAlignment.spaceBetween Left/right padding is 800 - (200
// * 4) / 4 = 100. The layout of the unselected item's title is
// slightly different; not checking that here.
expect(tester.getRect(find.byKey(title0)), const Rect.fromLTRB(100, 572, 300, 582));
expect(tester.getRect(find.byKey(icon0)), const Rect.fromLTRB(100, 562, 300, 572));
expect(tester.getRect(find.byKey(icon1)), const Rect.fromLTRB(500, 562, 700, 572));
});
testWidgets('BottomNavigationBar centered landscape layout', (WidgetTester tester) async {
final Key icon0 = UniqueKey();
final Key title0 = UniqueKey();
final Key icon1 = UniqueKey();
final Key title1 = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: Builder(
builder: (BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
currentIndex: 0,
landscapeLayout: BottomNavigationBarLandscapeLayout.centered,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: SizedBox(key: icon0, width: 200, height: 10),
title: SizedBox(key: title0, width: 200, height: 10),
),
BottomNavigationBarItem(
icon: SizedBox(key: icon1, width: 200, height: 10),
title: SizedBox(key: title1, width: 200, height: 10),
),
],
),
);
},
),
),
);
expect(tester.getSize(find.byType(BottomNavigationBar)), const Size(800, kBottomNavigationBarHeight));
expect(tester.getRect(find.byType(BottomNavigationBar)), const Rect.fromLTRB(0, 600 - kBottomNavigationBarHeight, 800, 600));
// The items are laid out as in the default case, within width=600
// (the "portrait" width) and the result is centered with the
// landscape width=800. So item 0's left edges are (800 - 600) / 2 +
// (600 - 400) / 4 = 150. Item 1's right edge is 800 - 150 =
// 650. The layout of the unselected item's title is slightly
// different; not checking that here.
expect(tester.getRect(find.byKey(title0)), const Rect.fromLTRB(150.0, 572.0, 350.0, 582.0));
expect(tester.getRect(find.byKey(icon0)), const Rect.fromLTRB(150, 562, 350, 572));
expect(tester.getRect(find.byKey(icon1)), const Rect.fromLTRB(450, 562, 650, 572));
});
testWidgets('BottomNavigationBar linear landscape layout', (WidgetTester tester) async {
final Key icon0 = UniqueKey();
final Key title0 = UniqueKey();
final Key icon1 = UniqueKey();
final Key title1 = UniqueKey();
await tester.pumpWidget(
MaterialApp(
home: Builder(
builder: (BuildContext context) {
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
currentIndex: 0,
landscapeLayout: BottomNavigationBarLandscapeLayout.linear,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: SizedBox(key: icon0, width: 100, height: 20),
title: SizedBox(key: title0, width: 100, height: 20),
),
BottomNavigationBarItem(
icon: SizedBox(key: icon1, width: 100, height: 20),
title: SizedBox(key: title1, width: 100, height: 20),
),
],
),
);
},
),
),
);
expect(tester.getSize(find.byType(BottomNavigationBar)), const Size(800, kBottomNavigationBarHeight));
expect(tester.getRect(find.byType(BottomNavigationBar)), const Rect.fromLTRB(0, 600 - kBottomNavigationBarHeight, 800, 600));
// The items are laid out as in the default case except each
// item's icon/title is arranged in a row, with 8 pixels in
// between the icon and title. The layout of the unselected
// item's title is slightly different; not checking that here.
expect(tester.getRect(find.byKey(title0)), const Rect.fromLTRB(204, 562, 304, 582));
expect(tester.getRect(find.byKey(icon0)), const Rect.fromLTRB(96, 562, 196, 582));
expect(tester.getRect(find.byKey(icon1)), const Rect.fromLTRB(496, 562, 596, 582));
});
} }
Widget boilerplate({ Widget? bottomNavigationBar, required TextDirection textDirection }) { Widget boilerplate({ Widget? bottomNavigationBar, required TextDirection textDirection }) {
......
...@@ -27,6 +27,7 @@ void main() { ...@@ -27,6 +27,7 @@ void main() {
expect(themeData.showSelectedLabels, null); expect(themeData.showSelectedLabels, null);
expect(themeData.showUnselectedLabels, null); expect(themeData.showUnselectedLabels, null);
expect(themeData.type, null); expect(themeData.type, null);
expect(themeData.landscapeLayout, null);
const BottomNavigationBarTheme theme = BottomNavigationBarTheme(data: BottomNavigationBarThemeData(), child: SizedBox()); const BottomNavigationBarTheme theme = BottomNavigationBarTheme(data: BottomNavigationBarThemeData(), child: SizedBox());
expect(theme.data.backgroundColor, null); expect(theme.data.backgroundColor, null);
...@@ -40,6 +41,7 @@ void main() { ...@@ -40,6 +41,7 @@ void main() {
expect(theme.data.showSelectedLabels, null); expect(theme.data.showSelectedLabels, null);
expect(theme.data.showUnselectedLabels, null); expect(theme.data.showUnselectedLabels, null);
expect(theme.data.type, null); expect(theme.data.type, null);
expect(themeData.landscapeLayout, null);
}); });
testWidgets('Default BottomNavigationBarThemeData debugFillProperties', (WidgetTester tester) async { testWidgets('Default BottomNavigationBarThemeData debugFillProperties', (WidgetTester tester) async {
...@@ -175,6 +177,7 @@ void main() { ...@@ -175,6 +177,7 @@ void main() {
const TextStyle themeSelectedTextStyle = TextStyle(fontSize: 22); const TextStyle themeSelectedTextStyle = TextStyle(fontSize: 22);
const TextStyle themeUnselectedTextStyle = TextStyle(fontSize: 21); const TextStyle themeUnselectedTextStyle = TextStyle(fontSize: 21);
const double themeElevation = 9.0; const double themeElevation = 9.0;
const BottomNavigationBarLandscapeLayout themeLandscapeLayout = BottomNavigationBarLandscapeLayout.centered;
const Color backgroundColor = Color(0xFF000004); const Color backgroundColor = Color(0xFF000004);
const Color selectedItemColor = Color(0xFF000005); const Color selectedItemColor = Color(0xFF000005);
...@@ -184,6 +187,7 @@ void main() { ...@@ -184,6 +187,7 @@ void main() {
const TextStyle selectedTextStyle = TextStyle(fontSize: 25); const TextStyle selectedTextStyle = TextStyle(fontSize: 25);
const TextStyle unselectedTextStyle = TextStyle(fontSize: 26); const TextStyle unselectedTextStyle = TextStyle(fontSize: 26);
const double elevation = 7.0; const double elevation = 7.0;
const BottomNavigationBarLandscapeLayout landscapeLayout = BottomNavigationBarLandscapeLayout.spread;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
...@@ -200,6 +204,7 @@ void main() { ...@@ -200,6 +204,7 @@ void main() {
type: BottomNavigationBarType.shifting, type: BottomNavigationBarType.shifting,
selectedLabelStyle: themeSelectedTextStyle, selectedLabelStyle: themeSelectedTextStyle,
unselectedLabelStyle: themeUnselectedTextStyle, unselectedLabelStyle: themeUnselectedTextStyle,
landscapeLayout: themeLandscapeLayout,
), ),
), ),
home: Scaffold( home: Scaffold(
...@@ -215,6 +220,7 @@ void main() { ...@@ -215,6 +220,7 @@ void main() {
type: BottomNavigationBarType.fixed, type: BottomNavigationBarType.fixed,
selectedLabelStyle: selectedTextStyle, selectedLabelStyle: selectedTextStyle,
unselectedLabelStyle: unselectedTextStyle, unselectedLabelStyle: unselectedTextStyle,
landscapeLayout: landscapeLayout,
items: const <BottomNavigationBarItem>[ items: const <BottomNavigationBarItem>[
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Icon(Icons.ac_unit), icon: Icon(Icons.ac_unit),
......
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