Revert "Add Material 3 support for BottomAppBar" (#114421)

This commit is contained in:
Zachary Anderson 2022-11-01 08:12:09 -07:00 committed by GitHub
parent 0e98194681
commit 210a2aa371
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 86 additions and 619 deletions

View file

@ -20,7 +20,6 @@ import 'dart:io';
import 'package:gen_defaults/action_chip_template.dart';
import 'package:gen_defaults/app_bar_template.dart';
import 'package:gen_defaults/banner_template.dart';
import 'package:gen_defaults/bottom_app_bar.dart';
import 'package:gen_defaults/bottom_sheet_template.dart';
import 'package:gen_defaults/button_template.dart';
import 'package:gen_defaults/card_template.dart';
@ -120,7 +119,6 @@ Future<void> main(List<String> args) async {
ActionChipTemplate('Chip', '$materialLib/chip.dart', tokens).updateFile();
ActionChipTemplate('ActionChip', '$materialLib/action_chip.dart', tokens).updateFile();
AppBarTemplate('AppBar', '$materialLib/app_bar.dart', tokens).updateFile();
BottomAppBarTemplate('BottomAppBar', '$materialLib/bottom_app_bar.dart', tokens).updateFile();
BannerTemplate('Banner', '$materialLib/banner.dart', tokens).updateFile();
BottomSheetTemplate('BottomSheet', '$materialLib/bottom_sheet.dart', tokens).updateFile();
ButtonTemplate('md.comp.elevated-button', 'ElevatedButton', '$materialLib/elevated_button.dart', tokens).updateFile();

View file

@ -1,32 +0,0 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'template.dart';
class BottomAppBarTemplate extends TokenTemplate {
const BottomAppBarTemplate(super.blockName, super.fileName, super.tokens);
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _${blockName}DefaultsM3 extends BottomAppBarTheme {
const _${blockName}DefaultsM3(this.context)
: super(
elevation: ${elevation('md.comp.bottom-app-bar.container')},
height: ${tokens['md.comp.bottom-app-bar.container.height']},
);
final BuildContext context;
@override
Color? get color => ${componentColor('md.comp.bottom-app-bar.container')};
@override
Color? get surfaceTintColor => ${componentColor('md.comp.bottom-app-bar.container.surface-tint-layer')};
@override
NotchedShape? get shape => const AutomaticNotchedShape(${shape('md.comp.bottom-app-bar.container')});
}
''';
}

View file

@ -1,193 +0,0 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flutter code sample for BottomAppBar with Material 3
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() {
runApp(const BottomAppBarDemo());
}
class BottomAppBarDemo extends StatefulWidget {
const BottomAppBarDemo({super.key});
@override
State createState() => _BottomAppBarDemoState();
}
class _BottomAppBarDemoState extends State<BottomAppBarDemo> {
static const List<Color> colors = <Color>[
Colors.yellow,
Colors.orange,
Colors.pink,
Colors.purple,
Colors.cyan,
];
static final List<Widget> items = List<Widget>.generate(
colors.length,
(int index) => Container(color: colors[index], height: 150.0),
).reversed.toList();
late ScrollController _controller;
bool _showFab = true;
bool _isElevated = true;
bool _isVisible = true;
FloatingActionButtonLocation get _fabLocation => _isVisible
? FloatingActionButtonLocation.endContained
: FloatingActionButtonLocation.endFloat;
void _listen() {
final ScrollDirection direction = _controller.position.userScrollDirection;
if (direction == ScrollDirection.forward) {
_show();
} else if (direction == ScrollDirection.reverse) {
_hide();
}
}
void _show() {
if (!_isVisible) {
setState(() => _isVisible = true);
}
}
void _hide() {
if (_isVisible) {
setState(() => _isVisible = false);
}
}
void _onShowFabChanged(bool value) {
setState(() {
_showFab = value;
});
}
void _onElevatedChanged(bool value) {
setState(() {
_isElevated = value;
});
}
void _addNewItem() {
setState(() {
items.insert(
0,
Container(color: colors[items.length % 5], height: 150.0),
);
});
}
@override
void initState() {
super.initState();
_controller = ScrollController();
_controller.addListener(_listen);
}
@override
void dispose() {
_controller.removeListener(_listen);
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: Scaffold(
appBar: AppBar(
title: const Text('Bottom App Bar Demo'),
),
body: Column(
children: <Widget>[
SwitchListTile(
title: const Text('Floating Action Button'),
value: _showFab,
onChanged: _onShowFabChanged,
),
SwitchListTile(
title: const Text('Bottom App Bar Elevation'),
value: _isElevated,
onChanged: _onElevatedChanged,
),
Expanded(
child: ListView(
controller: _controller,
children: items.toList(),
),
),
],
),
floatingActionButton: _showFab
? FloatingActionButton(
onPressed: _addNewItem,
tooltip: 'Add New Item',
elevation: _isVisible ? 0.0 : null,
child: const Icon(Icons.add),
)
: null,
floatingActionButtonLocation: _fabLocation,
bottomNavigationBar: _DemoBottomAppBar(isElevated: _isElevated, isVisible: _isVisible),
),
);
}
}
class _DemoBottomAppBar extends StatelessWidget {
const _DemoBottomAppBar({
required this.isElevated,
required this.isVisible,
});
final bool isElevated;
final bool isVisible;
@override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: const Duration(milliseconds: 200),
height: isVisible ? 80.0 : 0,
child: BottomAppBar(
elevation: isElevated ? null : 0.0,
child: Row(
children: <Widget>[
IconButton(
tooltip: 'Open popup menu',
icon: const Icon(Icons.more_vert),
onPressed: () {
final SnackBar snackBar = SnackBar(
content: const Text('Yay! A SnackBar!'),
action: SnackBarAction(
label: 'Undo',
onPressed: () {},
),
);
// Find the ScaffoldMessenger in the widget tree
// and use it to show a SnackBar.
ScaffoldMessenger.of(context).showSnackBar(snackBar);
},
),
IconButton(
tooltip: 'Search',
icon: const Icon(Icons.search),
onPressed: () {},
),
IconButton(
tooltip: 'Favorite',
icon: const Icon(Icons.favorite),
onPressed: () {},
),
],
),
),
);
}
}

View file

@ -14,7 +14,9 @@ import 'theme.dart';
// Examples can assume:
// late Widget bottomAppBarContents;
/// A container that is typically used with [Scaffold.bottomNavigationBar].
/// A container that is typically used with [Scaffold.bottomNavigationBar], and
/// can have a notch along the top that makes room for an overlapping
/// [FloatingActionButton].
///
/// Typically used with a [Scaffold] and a [FloatingActionButton].
///
@ -38,15 +40,6 @@ import 'theme.dart';
/// ** See code in examples/api/lib/material/bottom_app_bar/bottom_app_bar.1.dart **
/// {@end-tool}
///
/// {@tool dartpad}
/// This example shows Material 3 [BottomAppBar] with its expected look and behaviors.
///
/// This also includes an optional [FloatingActionButton], which illustrates
/// the [FloatingActionButtonLocation.endContained].
///
/// ** See code in examples/api/lib/material/bottom_app_bar/bottom_app_bar.2.dart **
/// {@end-tool}
///
/// See also:
///
/// * [NotchedShape] which calculates the notch for a notched [BottomAppBar].
@ -69,8 +62,6 @@ class BottomAppBar extends StatefulWidget {
this.clipBehavior = Clip.none,
this.notchMargin = 4.0,
this.child,
this.surfaceTintColor,
this.height,
}) : assert(elevation == null || elevation >= 0.0),
assert(notchMargin != null),
assert(clipBehavior != null);
@ -97,8 +88,8 @@ class BottomAppBar extends StatefulWidget {
/// value is non-negative.
///
/// If this property is null then [BottomAppBarTheme.elevation] of
/// [ThemeData.bottomAppBarTheme] is used. If that's null and
/// [ThemeData.useMaterial3] is true, than the default value is 3 else is 8.
/// [ThemeData.bottomAppBarTheme] is used. If that's null, the default value
/// is 8.
final double? elevation;
/// The notch that is made for the floating action button.
@ -119,23 +110,6 @@ class BottomAppBar extends StatefulWidget {
/// Not used if [shape] is null.
final double notchMargin;
/// The color used as an overlay on [color] to indicate elevation.
///
/// If this is null, no overlay will be applied. Otherwise the
/// color will be composited on top of [color] with an opacity related
/// to [elevation] and used to paint the background of the [BottomAppBar].
///
/// The default is null.
///
/// See [Material.surfaceTintColor] for more details on how this overlay is applied.
final Color? surfaceTintColor;
/// The double value used to indicate the height of the [BottomAppBar].
///
/// If this is null, the default value is the minimum in relation to the content,
/// unless [ThemeData.useMaterial3] is true, in which case it defaults to 80.0.
final double? height;
@override
State createState() => _BottomAppBarState();
}
@ -143,6 +117,7 @@ class BottomAppBar extends StatefulWidget {
class _BottomAppBarState extends State<BottomAppBar> {
late ValueListenable<ScaffoldGeometry> geometryListenable;
final GlobalKey materialKey = GlobalKey();
static const double _defaultElevation = 8.0;
@override
void didChangeDependencies() {
@ -152,13 +127,9 @@ class _BottomAppBarState extends State<BottomAppBar> {
@override
Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context);
final bool isMaterial3 = theme.useMaterial3;
final BottomAppBarTheme babTheme = BottomAppBarTheme.of(context);
final BottomAppBarTheme defaults = isMaterial3 ? _BottomAppBarDefaultsM3(context) : _BottomAppBarDefaultsM2(context);
final bool hasFab = Scaffold.of(context).hasFloatingActionButton;
final NotchedShape? notchedShape = widget.shape ?? babTheme.shape ?? defaults.shape;
final NotchedShape? notchedShape = widget.shape ?? babTheme.shape;
final CustomClipper<Path> clipper = notchedShape != null && hasFab
? _BottomAppBarClipper(
geometry: geometryListenable,
@ -167,33 +138,20 @@ class _BottomAppBarState extends State<BottomAppBar> {
notchMargin: widget.notchMargin,
)
: const ShapeBorderClipper(shape: RoundedRectangleBorder());
final double elevation = widget.elevation ?? babTheme.elevation ?? defaults.elevation!;
final double? height = widget.height ?? babTheme.height ?? defaults.height;
final Color color = widget.color ?? babTheme.color ?? defaults.color!;
final Color surfaceTintColor = widget.surfaceTintColor ?? babTheme.surfaceTintColor ?? defaults.surfaceTintColor!;
final Color effectiveColor = isMaterial3 ? color : ElevationOverlay.applyOverlay(context, color, elevation);
final Widget? child = isMaterial3 ? Padding(
padding: const EdgeInsets.symmetric(vertical: 12.0, horizontal: 16.0),
child: widget.child,
) : widget.child;
return SizedBox(
height: height,
child: PhysicalShape(
clipper: clipper,
elevation: elevation,
color: effectiveColor,
clipBehavior: widget.clipBehavior,
child: Material(
key: materialKey,
type: isMaterial3 ? MaterialType.canvas : MaterialType.transparency,
elevation: elevation,
surfaceTintColor: surfaceTintColor,
child: child == null
? null
: SafeArea(child: child),
),
final double elevation = widget.elevation ?? babTheme.elevation ?? _defaultElevation;
final Color color = widget.color ?? babTheme.color ?? Theme.of(context).bottomAppBarColor;
final Color effectiveColor = ElevationOverlay.applyOverlay(context, color, elevation);
return PhysicalShape(
clipper: clipper,
elevation: elevation,
color: effectiveColor,
clipBehavior: widget.clipBehavior,
child: Material(
key: materialKey,
type: MaterialType.transparency,
child: widget.child == null
? null
: SafeArea(child: widget.child!),
),
);
}
@ -245,49 +203,3 @@ class _BottomAppBarClipper extends CustomClipper<Path> {
|| oldClipper.notchMargin != notchMargin;
}
}
class _BottomAppBarDefaultsM2 extends BottomAppBarTheme {
const _BottomAppBarDefaultsM2(this.context)
: super(
elevation: 8.0,
);
final BuildContext context;
@override
Color? get color => Theme.of(context).bottomAppBarColor;
@override
Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
}
// BEGIN GENERATED TOKEN PROPERTIES - BottomAppBar
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: v0_101
// Generated version v0_101
class _BottomAppBarDefaultsM3 extends BottomAppBarTheme {
const _BottomAppBarDefaultsM3(this.context)
: super(
elevation: 3.0,
height: 80.0,
);
final BuildContext context;
@override
Color? get color => Theme.of(context).colorScheme.surface;
@override
Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
@override
NotchedShape? get shape => const AutomaticNotchedShape(RoundedRectangleBorder());
}
// END GENERATED TOKEN PROPERTIES - BottomAppBar

View file

@ -32,8 +32,6 @@ class BottomAppBarTheme with Diagnosticable {
this.color,
this.elevation,
this.shape,
this.height,
this.surfaceTintColor,
});
/// Default value for [BottomAppBar.color].
@ -47,33 +45,17 @@ class BottomAppBarTheme with Diagnosticable {
/// Default value for [BottomAppBar.shape].
final NotchedShape? shape;
/// Default value for [BottomAppBar.height].
///
/// If null, [BottomAppBar] height will be the minimum on the non material 3.
final double? height;
/// Default value for [BottomAppBar.surfaceTintColor].
///
/// If null, [BottomAppBar] will not display an overlay color.
///
/// See [Material.surfaceTintColor] for more details.
final Color? surfaceTintColor;
/// Creates a copy of this object but with the given fields replaced with the
/// new values.
BottomAppBarTheme copyWith({
Color? color,
double? elevation,
NotchedShape? shape,
double? height,
Color? surfaceTintColor,
}) {
return BottomAppBarTheme(
color: color ?? this.color,
elevation: elevation ?? this.elevation,
shape: shape ?? this.shape,
height: height ?? this.height,
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
);
}
@ -93,8 +75,6 @@ class BottomAppBarTheme with Diagnosticable {
color: Color.lerp(a?.color, b?.color, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t),
shape: t < 0.5 ? a?.shape : b?.shape,
height: lerpDouble(a?.height, b?.height, t),
surfaceTintColor: Color.lerp(a?.color, b?.color, t),
);
}
@ -103,8 +83,6 @@ class BottomAppBarTheme with Diagnosticable {
color,
elevation,
shape,
height,
surfaceTintColor,
);
@override
@ -118,9 +96,7 @@ class BottomAppBarTheme with Diagnosticable {
return other is BottomAppBarTheme
&& other.color == color
&& other.elevation == elevation
&& other.shape == shape
&& other.height == height
&& other.surfaceTintColor == surfaceTintColor;
&& other.shape == shape;
}
@override
@ -129,7 +105,5 @@ class BottomAppBarTheme with Diagnosticable {
properties.add(ColorProperty('color', color, defaultValue: null));
properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
properties.add(DiagnosticsProperty<NotchedShape>('shape', shape, defaultValue: null));
properties.add(DiagnosticsProperty<double>('height', height, defaultValue: null));
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
}
}

View file

@ -419,16 +419,6 @@ abstract class FloatingActionButtonLocation {
/// ![](https://flutter.github.io/assets-for-api-docs/assets/material/floating_action_button_location_mini_end_docked.png)
static const FloatingActionButtonLocation miniEndDocked = _MiniEndDockedFabLocation();
/// End-aligned [FloatingActionButton], floating over the
/// [Scaffold.bottomNavigationBar] so that the floating
/// action button lines up with the center of the bottom navigation bar.
///
/// This is unlikely to be a useful location for apps which has a [BottomNavigationBar]
/// or a non material 3 [BottomAppBar].
///
/// ![](https://flutter.github.io/assets-for-api-docs/assets/material/floating_action_button_location_end_contained.png)
static const FloatingActionButtonLocation endContained = _EndContainedFabLocation();
/// Places the [FloatingActionButton] based on the [Scaffold]'s layout.
///
/// This uses a [ScaffoldPrelayoutGeometry], which the [Scaffold] constructs
@ -619,34 +609,6 @@ mixin FabDockedOffsetY on StandardFabLocation {
}
}
/// Mixin for a "contained" floating action button location, such as [FloatingActionButtonLocation.endContained].
mixin FabContainedOffsetY on StandardFabLocation {
/// Calculates y-offset for [FloatingActionButtonLocation]s floating over the
/// [Scaffold.bottomNavigationBar] so that the center of the floating
/// action button lines up with the center of the bottom navigation bar.
@override
double getOffsetY(ScaffoldPrelayoutGeometry scaffoldGeometry, double adjustment) {
final double contentBottom = scaffoldGeometry.contentBottom;
final double contentMargin = scaffoldGeometry.scaffoldSize.height - contentBottom;
final double bottomViewPadding = scaffoldGeometry.minViewPadding.bottom;
final double fabHeight = scaffoldGeometry.floatingActionButtonSize.height;
final double bottomMinInset = scaffoldGeometry.minInsets.bottom;
double safeMargin = 0.0;
if (contentMargin > bottomMinInset + fabHeight / 2.0) {
// If contentMargin is higher than bottomMinInset enough to display the
// FAB without clipping, don't provide a margin
safeMargin = 0.0;
} else {
safeMargin = bottomViewPadding;
}
final double fabY = contentBottom - fabHeight / 2.0 - safeMargin;
final double maxFabY = scaffoldGeometry.scaffoldSize.height - fabHeight - safeMargin;
return math.min(maxFabY, fabY + contentMargin / 2);
}
}
/// Mixin for a "start" floating action button location, such as [FloatingActionButtonLocation.startTop].
mixin FabStartOffsetX on StandardFabLocation {
/// Calculates x-offset for start-aligned [FloatingActionButtonLocation]s.
@ -836,14 +798,6 @@ class _MiniEndDockedFabLocation extends StandardFabLocation
String toString() => 'FloatingActionButtonLocation.miniEndDocked';
}
class _EndContainedFabLocation extends StandardFabLocation
with FabEndOffsetX, FabContainedOffsetY {
const _EndContainedFabLocation();
@override
String toString() => 'FloatingActionButtonLocation.endContained';
}
/// Provider of animations to move the [FloatingActionButton] between [FloatingActionButtonLocation]s.
///
/// The [Scaffold] uses [Scaffold.floatingActionButtonAnimator] to define:

View file

@ -1288,7 +1288,6 @@ class ThemeData with Diagnosticable {
///
/// ### Components
/// * Common buttons: [ElevatedButton], [FilledButton], [OutlinedButton], [TextButton], [IconButton]
/// * Bottom app bar: [BottomAppBar]
/// * FAB: [FloatingActionButton]
/// * Extended FAB: [FloatingActionButton.extended]
/// * Cards: [Card]

View file

@ -10,215 +10,92 @@ import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('Material 2 tests', () {
testWidgets('BAB theme overrides color', (WidgetTester tester) async {
const Color themedColor = Colors.black87;
const BottomAppBarTheme theme = BottomAppBarTheme(color: themedColor);
testWidgets('BAB theme overrides color', (WidgetTester tester) async {
const Color themedColor = Colors.black87;
const BottomAppBarTheme theme = BottomAppBarTheme(color: themedColor);
await tester.pumpWidget(_withTheme(theme));
await tester.pumpWidget(_withTheme(theme));
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, themedColor);
});
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, themedColor);
});
testWidgets('BAB color - Widget', (WidgetTester tester) async {
const Color themeColor = Colors.white10;
const Color babThemeColor = Colors.black87;
const Color babColor = Colors.pink;
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
testWidgets('BAB color - Widget', (WidgetTester tester) async {
const Color themeColor = Colors.white10;
const Color babThemeColor = Colors.black87;
const Color babColor = Colors.pink;
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
bottomAppBarTheme: theme, bottomAppBarColor: themeColor),
home: const Scaffold(body: BottomAppBar(color: babColor)),
));
await tester.pumpWidget(MaterialApp(
theme: ThemeData(bottomAppBarTheme: theme, bottomAppBarColor: themeColor),
home: const Scaffold(body: BottomAppBar(color: babColor)),
));
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, babColor);
});
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, babColor);
});
testWidgets('BAB color - BabTheme', (WidgetTester tester) async {
const Color themeColor = Colors.white10;
const Color babThemeColor = Colors.black87;
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
testWidgets('BAB color - BabTheme', (WidgetTester tester) async {
const Color themeColor = Colors.white10;
const Color babThemeColor = Colors.black87;
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
bottomAppBarTheme: theme, bottomAppBarColor: themeColor),
home: const Scaffold(body: BottomAppBar()),
));
await tester.pumpWidget(MaterialApp(
theme: ThemeData(bottomAppBarTheme: theme, bottomAppBarColor: themeColor),
home: const Scaffold(body: BottomAppBar()),
));
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, babThemeColor);
});
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, babThemeColor);
});
testWidgets('BAB color - Theme', (WidgetTester tester) async {
const Color themeColor = Colors.white10;
testWidgets('BAB color - Theme', (WidgetTester tester) async {
const Color themeColor = Colors.white10;
await tester.pumpWidget(MaterialApp(
theme: ThemeData(bottomAppBarColor: themeColor),
home: const Scaffold(body: BottomAppBar()),
));
await tester.pumpWidget(MaterialApp(
theme: ThemeData(bottomAppBarColor: themeColor),
home: const Scaffold(body: BottomAppBar()),
));
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, themeColor);
});
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, themeColor);
});
testWidgets('BAB color - Default', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(),
home: const Scaffold(body: BottomAppBar()),
));
testWidgets('BAB color - Default', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(),
home: const Scaffold(body: BottomAppBar()),
));
final PhysicalShape widget = _getBabRenderObject(tester);
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, Colors.white);
});
expect(widget.color, Colors.white);
});
testWidgets('BAB theme customizes shape', (WidgetTester tester) async {
const BottomAppBarTheme theme = BottomAppBarTheme(
testWidgets('BAB theme customizes shape', (WidgetTester tester) async {
const BottomAppBarTheme theme = BottomAppBarTheme(
color: Colors.white30,
shape: CircularNotchedRectangle(),
elevation: 1.0,
);
);
await tester.pumpWidget(_withTheme(theme));
await tester.pumpWidget(_withTheme(theme));
await expectLater(
find.byKey(_painterKey),
matchesGoldenFile('bottom_app_bar_theme.custom_shape.png'),
);
});
testWidgets(
'BAB theme does not affect defaults', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(body: BottomAppBar()),
));
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, Colors.white);
expect(widget.elevation, equals(8.0));
});
await expectLater(
find.byKey(_painterKey),
matchesGoldenFile('bottom_app_bar_theme.custom_shape.png'),
);
});
group('Material 3 tests', () {
Material getBabRenderObject(WidgetTester tester) {
return tester.widget<Material>(
find.descendant(
of: find.byType(BottomAppBar),
matching: find.byType(Material),
),
);
}
testWidgets('BAB theme does not affect defaults', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(body: BottomAppBar()),
));
testWidgets('BAB theme overrides color - M3', (WidgetTester tester) async {
const Color themedColor = Colors.black87;
const BottomAppBarTheme theme = BottomAppBarTheme(
color: themedColor, elevation: 0);
final PhysicalShape widget = _getBabRenderObject(tester);
await tester.pumpWidget(_withTheme(theme, true));
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, themedColor);
});
testWidgets('BAB color - Widget - M3', (WidgetTester tester) async {
const Color themeColor = Colors.white10;
const Color babThemeColor = Colors.black87;
const Color babColor = Colors.pink;
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true,
bottomAppBarTheme: theme,
bottomAppBarColor: themeColor),
home: const Scaffold(body: BottomAppBar(color: babColor)),
));
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, babColor);
});
testWidgets('BAB color - BabTheme - M3', (WidgetTester tester) async {
const Color themeColor = Colors.white10;
const Color babThemeColor = Colors.black87;
const BottomAppBarTheme theme = BottomAppBarTheme(color: babThemeColor);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true,
bottomAppBarTheme: theme,
bottomAppBarColor: themeColor),
home: const Scaffold(body: BottomAppBar()),
));
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, babThemeColor);
});
testWidgets(
'BAB theme does not affect defaults - M3', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Scaffold(body: BottomAppBar()),
));
final PhysicalShape widget = _getBabRenderObject(tester);
expect(widget.color, Colors.white);
expect(widget.elevation, equals(3.0));
});
testWidgets('BAB theme overrides surfaceTintColor - M3', (
WidgetTester tester) async {
const Color babThemeSurfaceTintColor = Colors.black87;
const BottomAppBarTheme theme = BottomAppBarTheme(
surfaceTintColor: babThemeSurfaceTintColor, elevation: 0);
await tester.pumpWidget(_withTheme(theme, true));
final Material widget = getBabRenderObject(tester);
expect(widget.surfaceTintColor, babThemeSurfaceTintColor);
});
testWidgets(
'BAB surfaceTintColor - Widget - M3', (WidgetTester tester) async {
const Color themeSurfaceTintColor = Colors.white10;
const Color babThemeSurfaceTintColor = Colors.black87;
const Color babSurfaceTintColor = Colors.pink;
const BottomAppBarTheme theme = BottomAppBarTheme(
surfaceTintColor: babThemeSurfaceTintColor);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true,
bottomAppBarTheme: theme,
bottomAppBarColor: themeSurfaceTintColor),
home: const Scaffold(
body: BottomAppBar(surfaceTintColor: babSurfaceTintColor)),
));
final Material widget = getBabRenderObject(tester);
expect(widget.surfaceTintColor, babSurfaceTintColor);
});
testWidgets(
'BAB surfaceTintColor - BabTheme - M3', (WidgetTester tester) async {
const Color themeColor = Colors.white10;
const Color babThemeColor = Colors.black87;
const BottomAppBarTheme theme = BottomAppBarTheme(
surfaceTintColor: babThemeColor);
await tester.pumpWidget(MaterialApp(
theme: ThemeData(useMaterial3: true,
bottomAppBarTheme: theme,
bottomAppBarColor: themeColor),
home: const Scaffold(body: BottomAppBar()),
));
final Material widget = getBabRenderObject(tester);
expect(widget.surfaceTintColor, babThemeColor);
});
expect(widget.color, Colors.white);
expect(widget.elevation, equals(8.0));
});
}
@ -233,9 +110,9 @@ PhysicalShape _getBabRenderObject(WidgetTester tester) {
final Key _painterKey = UniqueKey();
Widget _withTheme(BottomAppBarTheme theme, [bool useMaterial3 = false]) {
Widget _withTheme(BottomAppBarTheme theme) {
return MaterialApp(
theme: ThemeData(useMaterial3: useMaterial3, bottomAppBarTheme: theme),
theme: ThemeData(bottomAppBarTheme: theme),
home: Scaffold(
floatingActionButton: const FloatingActionButton(onPressed: null),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,

View file

@ -296,21 +296,6 @@ void main() {
expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(756.0, 572.0));
});
testWidgets('Contained floating action button locations', (WidgetTester tester) async {
await tester.pumpWidget(
_buildFrame(
location: FloatingActionButtonLocation.endContained,
bab: const SizedBox(height: 100.0),
viewInsets: EdgeInsets.zero,
),
);
// Scaffold 800x600, FAB is 56x56, BAB is 800x100, FAB's center is
// at the top of the BAB.
// Formula: scaffold height - BAB height + FAB height / 2 + BAB top & bottom margins.
expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(756.0, 550.0));
});
testWidgets('Mini-start-top floating action button location', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
@ -445,12 +430,6 @@ void main() {
expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX, _dockedOffsetY));
});
testWidgets('endContained', (WidgetTester tester) async {
await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.endContained));
expect(tester.getCenter(find.byType(FloatingActionButton)), const Offset(_rightOffsetX, _containedOffsetY));
});
testWidgets('miniStartTop', (WidgetTester tester) async {
await tester.pumpWidget(_singleFabScaffold(FloatingActionButtonLocation.miniStartTop));
@ -1638,7 +1617,6 @@ const double _miniRightOffsetX = _rightOffsetX + kMiniButtonOffsetAdjustment;
const double _topOffsetY = 56.0;
const double _floatOffsetY = 500.0;
const double _dockedOffsetY = 544.0;
const double _containedOffsetY = 544.0 + 56.0 / 2;
const double _miniFloatOffsetY = _floatOffsetY + kMiniButtonOffsetAdjustment;
Widget _singleFabScaffold(