Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/material_ui/lib/src/bottom_navigation_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ class BottomNavigationBar extends StatefulWidget {
this.enableFeedback,
this.landscapeLayout,
this.useLegacyColorScheme = true,
this.splashRadius,
}) : assert(items.length >= 2),
assert(
items.every((BottomNavigationBarItem item) => item.label != null),
Expand All @@ -285,6 +286,7 @@ class BottomNavigationBar extends StatefulWidget {
),
assert(selectedFontSize >= 0.0),
assert(unselectedFontSize >= 0.0),
assert(splashRadius == null || splashRadius > 0.0),
selectedItemColor = selectedItemColor ?? fixedColor;

/// Defines the appearance of the button items that are arrayed within the
Expand Down Expand Up @@ -463,6 +465,12 @@ class BottomNavigationBar extends StatefulWidget {
/// To opt-in the new theming logic set the flag to `false`
final bool useLegacyColorScheme;

/// The radius of the ink splash for [BottomNavigationBarItem] tap effects.
///
/// If null, then the value of [BottomNavigationBarThemeData.splashRadius] is used.
/// If that is also null, the default splash radius of [InkResponse] is used.
final double? splashRadius;

@override
State<BottomNavigationBar> createState() => _BottomNavigationBarState();
}
Expand Down Expand Up @@ -491,6 +499,7 @@ class _BottomNavigationTile extends StatelessWidget {
required this.mouseCursor,
required this.enableFeedback,
required this.layout,
this.splashRadius,
});

final BottomNavigationBarType type;
Expand All @@ -512,6 +521,7 @@ class _BottomNavigationTile extends StatelessWidget {
final MouseCursor mouseCursor;
final bool enableFeedback;
final BottomNavigationBarLandscapeLayout layout;
final double? splashRadius;

@override
Widget build(BuildContext context) {
Expand Down Expand Up @@ -593,6 +603,7 @@ class _BottomNavigationTile extends StatelessWidget {
onTap: onTap,
mouseCursor: mouseCursor,
enableFeedback: enableFeedback,
radius: splashRadius,
child: Padding(
padding: EdgeInsets.only(top: topPadding, bottom: bottomPadding),
child: _Tile(
Expand Down Expand Up @@ -1111,6 +1122,7 @@ class _BottomNavigationBarState extends State<BottomNavigationBar> with TickerPr
indexLabel: localizations.tabLabel(tabIndex: i + 1, tabCount: widget.items.length),
mouseCursor: effectiveMouseCursor,
layout: layout,
splashRadius: widget.splashRadius ?? bottomTheme.splashRadius,
),
);
}
Expand Down
14 changes: 13 additions & 1 deletion packages/material_ui/lib/src/bottom_navigation_bar_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
this.enableFeedback,
this.landscapeLayout,
this.mouseCursor,
this.splashRadius,
});

/// The color of the [BottomNavigationBar] itself.
Expand Down Expand Up @@ -131,6 +132,11 @@ class BottomNavigationBarThemeData with Diagnosticable {
/// If specified, overrides the default value of [BottomNavigationBar.mouseCursor].
final WidgetStateProperty<MouseCursor?>? mouseCursor;

/// If specified, defines the splash radius for [BottomNavigationBar] item tap effects.
///
/// If [BottomNavigationBar.splashRadius] is provided, [splashRadius] is ignored.
final double? splashRadius;

/// Creates a copy of this object but with the given fields replaced with the
/// new values.
BottomNavigationBarThemeData copyWith({
Expand All @@ -148,6 +154,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
bool? enableFeedback,
BottomNavigationBarLandscapeLayout? landscapeLayout,
WidgetStateProperty<MouseCursor?>? mouseCursor,
double? splashRadius,
}) {
return BottomNavigationBarThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
Expand All @@ -164,6 +171,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
enableFeedback: enableFeedback ?? this.enableFeedback,
landscapeLayout: landscapeLayout ?? this.landscapeLayout,
mouseCursor: mouseCursor ?? this.mouseCursor,
splashRadius: splashRadius ?? this.splashRadius,
);
}

Expand Down Expand Up @@ -193,6 +201,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
enableFeedback: t < 0.5 ? a?.enableFeedback : b?.enableFeedback,
landscapeLayout: t < 0.5 ? a?.landscapeLayout : b?.landscapeLayout,
mouseCursor: t < 0.5 ? a?.mouseCursor : b?.mouseCursor,
splashRadius: lerpDouble(a?.splashRadius, b?.splashRadius, t),
);
}

Expand All @@ -212,6 +221,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
enableFeedback,
landscapeLayout,
mouseCursor,
splashRadius,
);

@override
Expand All @@ -236,7 +246,8 @@ class BottomNavigationBarThemeData with Diagnosticable {
other.type == type &&
other.enableFeedback == enableFeedback &&
other.landscapeLayout == landscapeLayout &&
other.mouseCursor == mouseCursor;
other.mouseCursor == mouseCursor &&
other.splashRadius == splashRadius;
}

@override
Expand Down Expand Up @@ -292,6 +303,7 @@ class BottomNavigationBarThemeData with Diagnosticable {
defaultValue: null,
),
);
properties.add(DoubleProperty('splashRadius', splashRadius, defaultValue: null));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
changelog: |
- Adds splashRadius property to BottomNavigationBar and BottomNavigationBarThemeData.
version: minor
71 changes: 71 additions & 0 deletions packages/material_ui/test/bottom_navigation_bar_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3127,6 +3127,77 @@ void main() {

expect(tester.getSemantics(find.text('B')), isSemantics(label: 'B\nTab 2 of 2'));
});

testWidgets('BottomNavigationBar splashRadius defaults to null', (WidgetTester tester) async {
await tester.pumpWidget(
boilerplate(
textDirection: TextDirection.ltr,
bottomNavigationBar: BottomNavigationBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.ac_unit), label: 'A'),
BottomNavigationBarItem(icon: Icon(Icons.access_alarm), label: 'B'),
],
),
),
);

final Iterable<InkResponse> inkResponses = tester.widgetList<InkResponse>(
find.descendant(of: find.byType(BottomNavigationBar), matching: find.byType(InkResponse)),
);
expect(inkResponses.length, 2);
for (final inkResponse in inkResponses) {
expect(inkResponse.radius, isNull);
}
});

testWidgets('BottomNavigationBar splashRadius test', (WidgetTester tester) async {
const splashRadius = 20.0;
await tester.pumpWidget(
boilerplate(
textDirection: TextDirection.ltr,
bottomNavigationBar: BottomNavigationBar(
splashRadius: splashRadius,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.ac_unit), label: 'A'),
BottomNavigationBarItem(icon: Icon(Icons.access_alarm), label: 'B'),
],
),
),
);

final Iterable<InkResponse> inkResponses = tester.widgetList<InkResponse>(
find.descendant(of: find.byType(BottomNavigationBar), matching: find.byType(InkResponse)),
);
expect(inkResponses.length, 2);
for (final inkResponse in inkResponses) {
expect(inkResponse.radius, splashRadius);
}
});

testWidgets('BottomNavigationBar assert when splashRadius is non-positive', (
WidgetTester tester,
) async {
expect(
() => BottomNavigationBar(
splashRadius: 0.0,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.ac_unit), label: 'A'),
BottomNavigationBarItem(icon: Icon(Icons.access_alarm), label: 'B'),
],
),
throwsAssertionError,
);
expect(
() => BottomNavigationBar(
splashRadius: -1.0,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.ac_unit), label: 'A'),
BottomNavigationBarItem(icon: Icon(Icons.access_alarm), label: 'B'),
],
),
throwsAssertionError,
);
});
}

Widget boilerplate({
Expand Down
21 changes: 19 additions & 2 deletions packages/material_ui/test/bottom_navigation_bar_theme_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ void main() {
expect(themeData.type, null);
expect(themeData.landscapeLayout, null);
expect(themeData.mouseCursor, null);
expect(themeData.splashRadius, null);

const theme = BottomNavigationBarTheme(data: BottomNavigationBarThemeData(), child: SizedBox());
expect(theme.data.backgroundColor, null);
Expand All @@ -50,8 +51,9 @@ void main() {
expect(theme.data.showSelectedLabels, null);
expect(theme.data.showUnselectedLabels, null);
expect(theme.data.type, null);
expect(themeData.landscapeLayout, null);
expect(themeData.mouseCursor, null);
expect(theme.data.landscapeLayout, null);
expect(theme.data.mouseCursor, null);
expect(theme.data.splashRadius, null);
});

testWidgets('Default BottomNavigationBarThemeData debugFillProperties', (
Expand Down Expand Up @@ -85,6 +87,7 @@ void main() {
showUnselectedLabels: true,
type: BottomNavigationBarType.fixed,
mouseCursor: WidgetStateMouseCursor.clickable,
splashRadius: 18.0,
).debugFillProperties(builder);

final List<String> description = builder.properties
Expand All @@ -109,6 +112,7 @@ void main() {
expect(description[9], 'showUnselectedLabels: true');
expect(description[10], 'type: BottomNavigationBarType.fixed');
expect(description[11], 'mouseCursor: WidgetStateMouseCursor(clickable)');
expect(description[12], 'splashRadius: 18.0');
});

testWidgets('BottomNavigationBar is themeable', (WidgetTester tester) async {
Expand Down Expand Up @@ -142,6 +146,7 @@ void main() {
}
return SystemMouseCursors.move;
}),
splashRadius: 28.0,
),
),
home: Scaffold(
Expand Down Expand Up @@ -196,6 +201,10 @@ void main() {
expect(_material(tester).elevation, equals(elevation));
expect(_material(tester).color, equals(backgroundColor));

for (final InkResponse inkResponse in tester.widgetList<InkResponse>(find.byType(InkResponse))) {
expect(inkResponse.radius, 28.0);
}

final Offset selectedBarItem = tester.getCenter(findACTransform);
final Offset unselectedBarItem = tester.getCenter(findAlarmTransform);
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
Expand Down Expand Up @@ -258,6 +267,7 @@ void main() {
unselectedLabelStyle: themeUnselectedTextStyle,
landscapeLayout: themeLandscapeLayout,
mouseCursor: themeCursor,
splashRadius: 28.0,
),
),
home: Scaffold(
Expand All @@ -275,6 +285,7 @@ void main() {
unselectedLabelStyle: unselectedTextStyle,
landscapeLayout: landscapeLayout,
mouseCursor: cursor,
splashRadius: 32.0,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(icon: Icon(Icons.ac_unit), label: 'AC'),
BottomNavigationBarItem(icon: Icon(Icons.access_alarm), label: 'Alarm'),
Expand Down Expand Up @@ -323,6 +334,12 @@ void main() {
expect(_material(tester).elevation, equals(elevation));
expect(_material(tester).color, equals(backgroundColor));

for (final InkResponse inkResponse in tester.widgetList<InkResponse>(
findDescendantOfBottomNavigationBar(find.byType(InkResponse)),
)) {
expect(inkResponse.radius, 32.0);
}

final Offset barItem = tester.getCenter(
findDescendantOfBottomNavigationBar(
find.ancestor(of: find.text('AC'), matching: find.byType(Transform)),
Expand Down