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

Added BottomNavigationBar landscapeLayout parameter (#87211)

parent c5866c5e
...@@ -34,6 +34,31 @@ enum BottomNavigationBarType { ...@@ -34,6 +34,31 @@ enum BottomNavigationBarType {
shifting, shifting,
} }
/// Refines the layout of a [BottomNavigationBar] when the enclosing
/// [MediaQueryData.orientation] is [Orientation.landscape].
enum BottomNavigationBarLandscapeLayout {
/// If the enclosing [MediaQueryData.orientation] is
/// [Orientation.landscape] then the navigation bar's items are
/// evenly spaced and spread out across the available width. Each
/// item's label and icon are arranged in a column.
spread,
/// If the enclosing [MediaQueryData.orientation] is
/// [Orientation.landscape] then the navigation bar's items are
/// evenly spaced in a row but only consume as much width as they
/// would in portrait orientation. The row of items is centered within
/// the available width. Each item's label and icon are arranged
/// in a column.
centered,
/// If the enclosing [MediaQueryData.orientation] is
/// [Orientation.landscape] then the navigation bar's items are
/// evenly spaced and each item's icon and label are lined up in a
/// row instead of a column.
linear,
}
/// A material widget that's displayed at the bottom of an app for selecting /// A material widget that's displayed at the bottom of an app for selecting
/// among a small number of views, typically between three and five. /// among a small number of views, typically between three and five.
/// ///
...@@ -277,6 +302,7 @@ class BottomNavigationBar extends StatefulWidget { ...@@ -277,6 +302,7 @@ class BottomNavigationBar extends StatefulWidget {
this.showUnselectedLabels, this.showUnselectedLabels,
this.mouseCursor, this.mouseCursor,
this.enableFeedback, this.enableFeedback,
this.landscapeLayout,
}) : assert(items != null), }) : assert(items != null),
assert(items.length >= 2), assert(items.length >= 2),
assert( assert(
...@@ -422,6 +448,40 @@ class BottomNavigationBar extends StatefulWidget { ...@@ -422,6 +448,40 @@ class BottomNavigationBar extends StatefulWidget {
/// * [Feedback] for providing platform-specific feedback to certain actions. /// * [Feedback] for providing platform-specific feedback to certain actions.
final bool? enableFeedback; final bool? enableFeedback;
/// The arrangement of the bar's [items] when the enclosing
/// [MediaQueryData.orientation] is [Orientation.landscape].
///
/// The following alternatives are supported:
///
/// * [BottomNavigationBarLandscapeLayout.spread] - the items are
/// evenly spaced and spread out across the available width. Each
/// item's label and icon are arranged in a column.
/// * [BottomNavigationBarLandscapeLayout.centered] - the items are
/// evenly spaced in a row but only consume as much width as they
/// would in portrait orientation. The row of items is centered within
/// the available width. Each item's label and icon are arranged
/// in a column.
/// * [BottomNavigationBarLandscapeLayout.linear] - the items are
/// evenly spaced and each item's icon and label are lined up in a
/// row instead of a column.
///
/// If this property is null, then the value of the enclosing
/// [BottomNavigationBarThemeData.landscapeLayout is used. If that
/// property is also null, then
/// [BottomNavigationBarLandscapeLayout.spread] is used.
///
/// This property is null by default.
///
/// See also:
///
/// * [ThemeData.bottomNavigationBarTheme] - which can be used to specify
/// bottom navigation bar defaults for an entire application.
/// * [BottomNavigationBarTheme] - which can be used to specify
/// bottom navigation bar defaults for a widget subtree.
/// * [MediaQuery.of] - which can be used to determing the current
/// orientation.
final BottomNavigationBarLandscapeLayout? landscapeLayout;
@override @override
State<BottomNavigationBar> createState() => _BottomNavigationBarState(); State<BottomNavigationBar> createState() => _BottomNavigationBarState();
} }
...@@ -447,13 +507,14 @@ class _BottomNavigationTile extends StatelessWidget { ...@@ -447,13 +507,14 @@ class _BottomNavigationTile extends StatelessWidget {
this.indexLabel, this.indexLabel,
required this.mouseCursor, required this.mouseCursor,
required this.enableFeedback, required this.enableFeedback,
}) : assert(type != null), required this.layout,
assert(item != null), }) : assert(type != null),
assert(animation != null), assert(item != null),
assert(selected != null), assert(animation != null),
assert(selectedLabelStyle != null), assert(selected != null),
assert(unselectedLabelStyle != null), assert(selectedLabelStyle != null),
assert(mouseCursor != null); assert(unselectedLabelStyle != null),
assert(mouseCursor != null);
final BottomNavigationBarType type; final BottomNavigationBarType type;
final BottomNavigationBarItem item; final BottomNavigationBarItem item;
...@@ -472,6 +533,7 @@ class _BottomNavigationTile extends StatelessWidget { ...@@ -472,6 +533,7 @@ class _BottomNavigationTile extends StatelessWidget {
final bool showUnselectedLabels; final bool showUnselectedLabels;
final MouseCursor mouseCursor; final MouseCursor mouseCursor;
final bool enableFeedback; final bool enableFeedback;
final BottomNavigationBarLandscapeLayout layout;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
...@@ -559,30 +621,26 @@ class _BottomNavigationTile extends StatelessWidget { ...@@ -559,30 +621,26 @@ class _BottomNavigationTile extends StatelessWidget {
enableFeedback: enableFeedback, enableFeedback: enableFeedback,
child: Padding( child: Padding(
padding: EdgeInsets.only(top: topPadding, bottom: bottomPadding), padding: EdgeInsets.only(top: topPadding, bottom: bottomPadding),
child: Column( child: _Tile(
crossAxisAlignment: CrossAxisAlignment.center, layout: layout,
mainAxisAlignment: MainAxisAlignment.spaceBetween, icon: _TileIcon(
mainAxisSize: MainAxisSize.min, colorTween: colorTween!,
children: <Widget>[ animation: animation,
_TileIcon( iconSize: iconSize,
colorTween: colorTween!, selected: selected,
animation: animation, item: item,
iconSize: iconSize, selectedIconTheme: selectedIconTheme,
selected: selected, unselectedIconTheme: unselectedIconTheme,
item: item, ),
selectedIconTheme: selectedIconTheme, label: _Label(
unselectedIconTheme: unselectedIconTheme, colorTween: colorTween!,
), animation: animation,
_Label( item: item,
colorTween: colorTween!, selectedLabelStyle: selectedLabelStyle,
animation: animation, unselectedLabelStyle: unselectedLabelStyle,
item: item, showSelectedLabels: showSelectedLabels,
selectedLabelStyle: selectedLabelStyle, showUnselectedLabels: showUnselectedLabels,
unselectedLabelStyle: unselectedLabelStyle, ),
showSelectedLabels: showSelectedLabels,
showUnselectedLabels: showUnselectedLabels,
),
],
), ),
), ),
); );
...@@ -618,6 +676,44 @@ class _BottomNavigationTile extends StatelessWidget { ...@@ -618,6 +676,44 @@ class _BottomNavigationTile extends StatelessWidget {
} }
// If the orientaion is landscape and layout is
// BottomNavigationBarLandscapeLayout.linear then return a
// icon-space-label row, where space is 8 pixels. Otherwise return a
// icon-label column.
class _Tile extends StatelessWidget {
const _Tile({
Key? key,
required this.layout,
required this.icon,
required this.label
}) : super(key: key);
final BottomNavigationBarLandscapeLayout layout;
final Widget icon;
final Widget label;
@override
Widget build(BuildContext context) {
final MediaQueryData data = MediaQuery.of(context);
if (data.orientation == Orientation.landscape && layout == BottomNavigationBarLandscapeLayout.linear) {
return Align(
heightFactor: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[icon, const SizedBox(width: 8), label],
),
);
}
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
mainAxisSize: MainAxisSize.min,
children: <Widget>[icon, label],
);
}
}
class _TileIcon extends StatelessWidget { class _TileIcon extends StatelessWidget {
const _TileIcon({ const _TileIcon({
Key? key, Key? key,
...@@ -917,7 +1013,7 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr ...@@ -917,7 +1013,7 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
return textStyle.fontSize == null ? textStyle.copyWith(fontSize: fontSize) : textStyle; return textStyle.fontSize == null ? textStyle.copyWith(fontSize: fontSize) : textStyle;
} }
List<Widget> _createTiles() { List<Widget> _createTiles(BottomNavigationBarLandscapeLayout layout) {
final MaterialLocalizations localizations = MaterialLocalizations.of(context); final MaterialLocalizations localizations = MaterialLocalizations.of(context);
assert(localizations != null); assert(localizations != null);
...@@ -993,21 +1089,12 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr ...@@ -993,21 +1089,12 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
showUnselectedLabels: widget.showUnselectedLabels ?? bottomTheme.showUnselectedLabels ?? _defaultShowUnselected, showUnselectedLabels: widget.showUnselectedLabels ?? bottomTheme.showUnselectedLabels ?? _defaultShowUnselected,
indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: widget.items.length), indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: widget.items.length),
mouseCursor: effectiveMouseCursor, mouseCursor: effectiveMouseCursor,
layout: layout,
)); ));
} }
return tiles; return tiles;
} }
Widget _createContainer(List<Widget> tiles) {
return DefaultTextStyle.merge(
overflow: TextOverflow.ellipsis,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: tiles,
),
);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(debugCheckHasDirectionality(context)); assert(debugCheckHasDirectionality(context));
...@@ -1016,7 +1103,11 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr ...@@ -1016,7 +1103,11 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
assert(Overlay.of(context, debugRequiredFor: widget) != null); assert(Overlay.of(context, debugRequiredFor: widget) != null);
final BottomNavigationBarThemeData bottomTheme = BottomNavigationBarTheme.of(context); final BottomNavigationBarThemeData bottomTheme = BottomNavigationBarTheme.of(context);
final BottomNavigationBarLandscapeLayout layout = widget.landscapeLayout
?? bottomTheme.landscapeLayout
?? BottomNavigationBarLandscapeLayout.spread;
final double additionalBottomPadding = MediaQuery.of(context).padding.bottom; final double additionalBottomPadding = MediaQuery.of(context).padding.bottom;
Color? backgroundColor; Color? backgroundColor;
switch (_effectiveType) { switch (_effectiveType) {
case BottomNavigationBarType.fixed: case BottomNavigationBarType.fixed:
...@@ -1026,9 +1117,11 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr ...@@ -1026,9 +1117,11 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
backgroundColor = _backgroundColor; backgroundColor = _backgroundColor;
break; break;
} }
return Semantics( return Semantics(
explicitChildNodes: true, explicitChildNodes: true,
child: Material( child: _Bar(
layout: layout,
elevation: widget.elevation ?? bottomTheme.elevation ?? 8.0, elevation: widget.elevation ?? bottomTheme.elevation ?? 8.0,
color: backgroundColor, color: backgroundColor,
child: ConstrainedBox( child: ConstrainedBox(
...@@ -1045,7 +1138,13 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr ...@@ -1045,7 +1138,13 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
child: MediaQuery.removePadding( child: MediaQuery.removePadding(
context: context, context: context,
removeBottom: true, removeBottom: true,
child: _createContainer(_createTiles()), child: DefaultTextStyle.merge(
overflow: TextOverflow.ellipsis,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: _createTiles(layout),
),
),
), ),
), ),
), ),
...@@ -1056,6 +1155,44 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr ...@@ -1056,6 +1155,44 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
} }
} }
// Optionally center a Material child for landscape layouts when layout is
// BottomNavigationBarLandscapeLayout.centered
class _Bar extends StatelessWidget {
const _Bar({
Key? key,
required this.child,
required this.layout,
required this.elevation,
required this.color,
}) : super(key: key);
final Widget child;
final BottomNavigationBarLandscapeLayout layout;
final double elevation;
final Color? color;
@override
Widget build(BuildContext context) {
final MediaQueryData data = MediaQuery.of(context);
Widget alignedChild = child;
if (data.orientation == Orientation.landscape && layout == BottomNavigationBarLandscapeLayout.centered) {
alignedChild = Align(
alignment: Alignment.bottomCenter,
heightFactor: 1,
child: SizedBox(
width: data.size.height,
child: child,
),
);
}
return Material(
elevation: elevation,
color: color,
child: alignedChild,
);
}
}
// Describes an animating color splash circle. // Describes an animating color splash circle.
class _Circle { class _Circle {
_Circle({ _Circle({
......
...@@ -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