Unverified Commit 746ce203 authored by Darren Austin's avatar Darren Austin Committed by GitHub

Added the ability to constrain the size of bottom sheets. (#80527)

parent 21fd5cdd
...@@ -78,6 +78,7 @@ class BottomSheet extends StatefulWidget { ...@@ -78,6 +78,7 @@ class BottomSheet extends StatefulWidget {
this.elevation, this.elevation,
this.shape, this.shape,
this.clipBehavior, this.clipBehavior,
this.constraints,
required this.onClosing, required this.onClosing,
required this.builder, required this.builder,
}) : assert(enableDrag != null), }) : assert(enableDrag != null),
...@@ -162,6 +163,23 @@ class BottomSheet extends StatefulWidget { ...@@ -162,6 +163,23 @@ class BottomSheet extends StatefulWidget {
/// will be [Clip.none]. /// will be [Clip.none].
final Clip? clipBehavior; final Clip? clipBehavior;
/// Defines minimum and maximum sizes for a [BottomSheet].
///
/// Typically a bottom sheet will cover the entire width of its
/// parent. However for large screens you may want to limit the width
/// to something smaller and this property provides a way to specify
/// a maximum width.
///
/// If null, then the ambient [ThemeData.bottomSheetTheme]'s
/// [BottomSheetThemeData.constraints] will be used. If that
/// is null then the bottom sheet's size will be constrained
/// by its parent (usually a [Scaffold]).
///
/// If constraints are specified (either in this property or in the
/// theme), the bottom sheet will be aligned to the bottom-center of
/// the available space. Otherwise, no alignment is applied.
final BoxConstraints? constraints;
@override @override
_BottomSheetState createState() => _BottomSheetState(); _BottomSheetState createState() => _BottomSheetState();
...@@ -244,12 +262,13 @@ class _BottomSheetState extends State<BottomSheet> { ...@@ -244,12 +262,13 @@ class _BottomSheetState extends State<BottomSheet> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final BottomSheetThemeData bottomSheetTheme = Theme.of(context).bottomSheetTheme; final BottomSheetThemeData bottomSheetTheme = Theme.of(context).bottomSheetTheme;
final BoxConstraints? constraints = widget.constraints ?? bottomSheetTheme.constraints;
final Color? color = widget.backgroundColor ?? bottomSheetTheme.backgroundColor; final Color? color = widget.backgroundColor ?? bottomSheetTheme.backgroundColor;
final double elevation = widget.elevation ?? bottomSheetTheme.elevation ?? 0; final double elevation = widget.elevation ?? bottomSheetTheme.elevation ?? 0;
final ShapeBorder? shape = widget.shape ?? bottomSheetTheme.shape; final ShapeBorder? shape = widget.shape ?? bottomSheetTheme.shape;
final Clip clipBehavior = widget.clipBehavior ?? bottomSheetTheme.clipBehavior ?? Clip.none; final Clip clipBehavior = widget.clipBehavior ?? bottomSheetTheme.clipBehavior ?? Clip.none;
final Widget bottomSheet = Material( Widget bottomSheet = Material(
key: _childKey, key: _childKey,
color: color, color: color,
elevation: elevation, elevation: elevation,
...@@ -260,6 +279,17 @@ class _BottomSheetState extends State<BottomSheet> { ...@@ -260,6 +279,17 @@ class _BottomSheetState extends State<BottomSheet> {
child: widget.builder(context), child: widget.builder(context),
), ),
); );
if (constraints != null) {
bottomSheet = Align(
alignment: Alignment.bottomCenter,
child: ConstrainedBox(
constraints: constraints,
child: bottomSheet,
),
);
}
return !widget.enableDrag ? bottomSheet : GestureDetector( return !widget.enableDrag ? bottomSheet : GestureDetector(
onVerticalDragStart: _handleDragStart, onVerticalDragStart: _handleDragStart,
onVerticalDragUpdate: _handleDragUpdate, onVerticalDragUpdate: _handleDragUpdate,
...@@ -313,6 +343,7 @@ class _ModalBottomSheet<T> extends StatefulWidget { ...@@ -313,6 +343,7 @@ class _ModalBottomSheet<T> extends StatefulWidget {
this.elevation, this.elevation,
this.shape, this.shape,
this.clipBehavior, this.clipBehavior,
this.constraints,
this.isScrollControlled = false, this.isScrollControlled = false,
this.enableDrag = true, this.enableDrag = true,
}) : assert(isScrollControlled != null), }) : assert(isScrollControlled != null),
...@@ -325,6 +356,7 @@ class _ModalBottomSheet<T> extends StatefulWidget { ...@@ -325,6 +356,7 @@ class _ModalBottomSheet<T> extends StatefulWidget {
final double? elevation; final double? elevation;
final ShapeBorder? shape; final ShapeBorder? shape;
final Clip? clipBehavior; final Clip? clipBehavior;
final BoxConstraints? constraints;
final bool enableDrag; final bool enableDrag;
@override @override
...@@ -382,6 +414,7 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> { ...@@ -382,6 +414,7 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
elevation: widget.elevation, elevation: widget.elevation,
shape: widget.shape, shape: widget.shape,
clipBehavior: widget.clipBehavior, clipBehavior: widget.clipBehavior,
constraints: widget.constraints,
enableDrag: widget.enableDrag, enableDrag: widget.enableDrag,
onDragStart: handleDragStart, onDragStart: handleDragStart,
onDragEnd: handleDragEnd, onDragEnd: handleDragEnd,
...@@ -418,6 +451,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> { ...@@ -418,6 +451,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
this.elevation, this.elevation,
this.shape, this.shape,
this.clipBehavior, this.clipBehavior,
this.constraints,
this.modalBarrierColor, this.modalBarrierColor,
this.isDismissible = true, this.isDismissible = true,
this.enableDrag = true, this.enableDrag = true,
...@@ -436,6 +470,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> { ...@@ -436,6 +470,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
final double? elevation; final double? elevation;
final ShapeBorder? shape; final ShapeBorder? shape;
final Clip? clipBehavior; final Clip? clipBehavior;
final BoxConstraints? constraints;
final Color? modalBarrierColor; final Color? modalBarrierColor;
final bool isDismissible; final bool isDismissible;
final bool enableDrag; final bool enableDrag;
...@@ -481,6 +516,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> { ...@@ -481,6 +516,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
elevation: elevation ?? sheetTheme.modalElevation ?? sheetTheme.elevation, elevation: elevation ?? sheetTheme.modalElevation ?? sheetTheme.elevation,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
constraints: constraints,
isScrollControlled: isScrollControlled, isScrollControlled: isScrollControlled,
enableDrag: enableDrag, enableDrag: enableDrag,
); );
...@@ -582,9 +618,11 @@ class _BottomSheetSuspendedCurve extends ParametricCurve<double> { ...@@ -582,9 +618,11 @@ class _BottomSheetSuspendedCurve extends ParametricCurve<double> {
/// The [enableDrag] parameter specifies whether the bottom sheet can be /// The [enableDrag] parameter specifies whether the bottom sheet can be
/// dragged up and down and dismissed by swiping downwards. /// dragged up and down and dismissed by swiping downwards.
/// ///
/// The optional [backgroundColor], [elevation], [shape], [clipBehavior] and [transitionAnimationController] /// The optional [backgroundColor], [elevation], [shape], [clipBehavior],
/// [constraints] and [transitionAnimationController]
/// parameters can be passed in to customize the appearance and behavior of /// parameters can be passed in to customize the appearance and behavior of
/// modal bottom sheets. /// modal bottom sheets (see the documentation for these on [BottomSheet]
/// for more details).
/// ///
/// The [transitionAnimationController] controls the bottom sheet's entrance and /// The [transitionAnimationController] controls the bottom sheet's entrance and
/// exit animations if provided. /// exit animations if provided.
...@@ -653,6 +691,7 @@ Future<T?> showModalBottomSheet<T>({ ...@@ -653,6 +691,7 @@ Future<T?> showModalBottomSheet<T>({
double? elevation, double? elevation,
ShapeBorder? shape, ShapeBorder? shape,
Clip? clipBehavior, Clip? clipBehavior,
BoxConstraints? constraints,
Color? barrierColor, Color? barrierColor,
bool isScrollControlled = false, bool isScrollControlled = false,
bool useRootNavigator = false, bool useRootNavigator = false,
...@@ -680,6 +719,7 @@ Future<T?> showModalBottomSheet<T>({ ...@@ -680,6 +719,7 @@ Future<T?> showModalBottomSheet<T>({
elevation: elevation, elevation: elevation,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
constraints: constraints,
isDismissible: isDismissible, isDismissible: isDismissible,
modalBarrierColor: barrierColor, modalBarrierColor: barrierColor,
enableDrag: enableDrag, enableDrag: enableDrag,
...@@ -694,9 +734,11 @@ Future<T?> showModalBottomSheet<T>({ ...@@ -694,9 +734,11 @@ Future<T?> showModalBottomSheet<T>({
/// Returns a controller that can be used to close and otherwise manipulate the /// Returns a controller that can be used to close and otherwise manipulate the
/// bottom sheet. /// bottom sheet.
/// ///
/// The optional [backgroundColor], [elevation], [shape], [clipBehavior] and [transitionAnimationController] /// The optional [backgroundColor], [elevation], [shape], [clipBehavior],
/// [constraints] and [transitionAnimationController]
/// parameters can be passed in to customize the appearance and behavior of /// parameters can be passed in to customize the appearance and behavior of
/// persistent bottom sheets. /// persistent bottom sheets (see the documentation for these on [BottomSheet]
/// for more details).
/// ///
/// To rebuild the bottom sheet (e.g. if it is stateful), call /// To rebuild the bottom sheet (e.g. if it is stateful), call
/// [PersistentBottomSheetController.setState] on the controller returned by /// [PersistentBottomSheetController.setState] on the controller returned by
...@@ -734,6 +776,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({ ...@@ -734,6 +776,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({
double? elevation, double? elevation,
ShapeBorder? shape, ShapeBorder? shape,
Clip? clipBehavior, Clip? clipBehavior,
BoxConstraints? constraints,
AnimationController? transitionAnimationController, AnimationController? transitionAnimationController,
}) { }) {
assert(context != null); assert(context != null);
...@@ -746,6 +789,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({ ...@@ -746,6 +789,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({
elevation: elevation, elevation: elevation,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
constraints: constraints,
transitionAnimationController: transitionAnimationController, transitionAnimationController: transitionAnimationController,
); );
} }
...@@ -34,6 +34,7 @@ class BottomSheetThemeData with Diagnosticable { ...@@ -34,6 +34,7 @@ class BottomSheetThemeData with Diagnosticable {
this.modalElevation, this.modalElevation,
this.shape, this.shape,
this.clipBehavior, this.clipBehavior,
this.constraints,
}); });
/// Default value for [BottomSheet.backgroundColor]. /// Default value for [BottomSheet.backgroundColor].
...@@ -67,6 +68,11 @@ class BottomSheetThemeData with Diagnosticable { ...@@ -67,6 +68,11 @@ class BottomSheetThemeData with Diagnosticable {
/// If null, [BottomSheet] uses [Clip.none]. /// If null, [BottomSheet] uses [Clip.none].
final Clip? clipBehavior; final Clip? clipBehavior;
/// Constrains the size of the [BottomSheet].
///
/// If null, the bottom sheet's size will be unconstrained.
final BoxConstraints? constraints;
/// Creates a copy of this object with the given fields replaced with the /// Creates a copy of this object with the given fields replaced with the
/// new values. /// new values.
BottomSheetThemeData copyWith({ BottomSheetThemeData copyWith({
...@@ -76,6 +82,7 @@ class BottomSheetThemeData with Diagnosticable { ...@@ -76,6 +82,7 @@ class BottomSheetThemeData with Diagnosticable {
double? modalElevation, double? modalElevation,
ShapeBorder? shape, ShapeBorder? shape,
Clip? clipBehavior, Clip? clipBehavior,
BoxConstraints? constraints,
}) { }) {
return BottomSheetThemeData( return BottomSheetThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor, backgroundColor: backgroundColor ?? this.backgroundColor,
...@@ -84,6 +91,7 @@ class BottomSheetThemeData with Diagnosticable { ...@@ -84,6 +91,7 @@ class BottomSheetThemeData with Diagnosticable {
modalElevation: modalElevation ?? this.modalElevation, modalElevation: modalElevation ?? this.modalElevation,
shape: shape ?? this.shape, shape: shape ?? this.shape,
clipBehavior: clipBehavior ?? this.clipBehavior, clipBehavior: clipBehavior ?? this.clipBehavior,
constraints: constraints ?? this.constraints,
); );
} }
...@@ -103,6 +111,7 @@ class BottomSheetThemeData with Diagnosticable { ...@@ -103,6 +111,7 @@ class BottomSheetThemeData with Diagnosticable {
modalElevation: lerpDouble(a?.modalElevation, b?.modalElevation, t), modalElevation: lerpDouble(a?.modalElevation, b?.modalElevation, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t), shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
clipBehavior: t < 0.5 ? a?.clipBehavior : b?.clipBehavior, clipBehavior: t < 0.5 ? a?.clipBehavior : b?.clipBehavior,
constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t),
); );
} }
...@@ -115,6 +124,7 @@ class BottomSheetThemeData with Diagnosticable { ...@@ -115,6 +124,7 @@ class BottomSheetThemeData with Diagnosticable {
modalElevation, modalElevation,
shape, shape,
clipBehavior, clipBehavior,
constraints,
); );
} }
...@@ -130,7 +140,8 @@ class BottomSheetThemeData with Diagnosticable { ...@@ -130,7 +140,8 @@ class BottomSheetThemeData with Diagnosticable {
&& other.modalBackgroundColor == modalBackgroundColor && other.modalBackgroundColor == modalBackgroundColor
&& other.modalElevation == modalElevation && other.modalElevation == modalElevation
&& other.shape == shape && other.shape == shape
&& other.clipBehavior == clipBehavior; && other.clipBehavior == clipBehavior
&& other.constraints == constraints;
} }
@override @override
...@@ -142,5 +153,6 @@ class BottomSheetThemeData with Diagnosticable { ...@@ -142,5 +153,6 @@ class BottomSheetThemeData with Diagnosticable {
properties.add(DoubleProperty('modalElevation', modalElevation, defaultValue: null)); properties.add(DoubleProperty('modalElevation', modalElevation, defaultValue: null));
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null)); properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
properties.add(DiagnosticsProperty<Clip>('clipBehavior', clipBehavior, defaultValue: null)); properties.add(DiagnosticsProperty<Clip>('clipBehavior', clipBehavior, defaultValue: null));
properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null));
} }
} }
...@@ -2481,6 +2481,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto ...@@ -2481,6 +2481,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
double? elevation, double? elevation,
ShapeBorder? shape, ShapeBorder? shape,
Clip? clipBehavior, Clip? clipBehavior,
BoxConstraints? constraints,
}) { }) {
assert(() { assert(() {
if (widget.bottomSheet != null && isPersistent && _currentBottomSheet != null) { if (widget.bottomSheet != null && isPersistent && _currentBottomSheet != null) {
...@@ -2554,6 +2555,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto ...@@ -2554,6 +2555,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
elevation: elevation, elevation: elevation,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
constraints: constraints,
); );
if (!isPersistent) if (!isPersistent)
...@@ -2653,6 +2655,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto ...@@ -2653,6 +2655,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
double? elevation, double? elevation,
ShapeBorder? shape, ShapeBorder? shape,
Clip? clipBehavior, Clip? clipBehavior,
BoxConstraints? constraints,
AnimationController? transitionAnimationController, AnimationController? transitionAnimationController,
}) { }) {
assert(() { assert(() {
...@@ -2678,6 +2681,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto ...@@ -2678,6 +2681,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
elevation: elevation, elevation: elevation,
shape: shape, shape: shape,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
constraints: constraints,
); );
}); });
return _currentBottomSheet! as PersistentBottomSheetController<T>; return _currentBottomSheet! as PersistentBottomSheetController<T>;
...@@ -3356,6 +3360,7 @@ class _StandardBottomSheet extends StatefulWidget { ...@@ -3356,6 +3360,7 @@ class _StandardBottomSheet extends StatefulWidget {
this.elevation, this.elevation,
this.shape, this.shape,
this.clipBehavior, this.clipBehavior,
this.constraints,
}) : super(key: key); }) : super(key: key);
final AnimationController animationController; // we control it, but it must be disposed by whoever created it. final AnimationController animationController; // we control it, but it must be disposed by whoever created it.
...@@ -3368,6 +3373,7 @@ class _StandardBottomSheet extends StatefulWidget { ...@@ -3368,6 +3373,7 @@ class _StandardBottomSheet extends StatefulWidget {
final double? elevation; final double? elevation;
final ShapeBorder? shape; final ShapeBorder? shape;
final Clip? clipBehavior; final Clip? clipBehavior;
final BoxConstraints? constraints;
@override @override
_StandardBottomSheetState createState() => _StandardBottomSheetState(); _StandardBottomSheetState createState() => _StandardBottomSheetState();
...@@ -3472,6 +3478,7 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> { ...@@ -3472,6 +3478,7 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
elevation: widget.elevation, elevation: widget.elevation,
shape: widget.shape, shape: widget.shape,
clipBehavior: widget.clipBehavior, clipBehavior: widget.clipBehavior,
constraints: widget.constraints,
), ),
), ),
); );
......
...@@ -833,6 +833,219 @@ void main() { ...@@ -833,6 +833,219 @@ void main() {
// The bottom sheet should not be showing any longer. // The bottom sheet should not be showing any longer.
expect(find.text('BottomSheet'), findsNothing); expect(find.text('BottomSheet'), findsNothing);
}); });
group('constraints', () {
testWidgets('No constraints by default for bottomSheet property', (WidgetTester tester) async {
await tester.pumpWidget(const MaterialApp(
home: Scaffold(
body: Center(child: Text('body')),
bottomSheet: Text('BottomSheet'),
),
));
expect(find.text('BottomSheet'), findsOneWidget);
expect(tester.getRect(find.text('BottomSheet')),
const Rect.fromLTRB(0, 586, 154, 600));
});
testWidgets('No constraints by default for showBottomSheet', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Builder(builder: (BuildContext context) {
return Center(
child: ElevatedButton(
child: const Text('Press me'),
onPressed: () {
Scaffold.of(context).showBottomSheet<void>(
(BuildContext context) => const Text('BottomSheet')
);
},
),
);
}),
),
));
expect(find.text('BottomSheet'), findsNothing);
await tester.tap(find.text('Press me'));
await tester.pumpAndSettle();
expect(find.text('BottomSheet'), findsOneWidget);
expect(tester.getRect(find.text('BottomSheet')),
const Rect.fromLTRB(0, 586, 154, 600));
});
testWidgets('No constraints by default for showModalBottomSheet', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Builder(builder: (BuildContext context) {
return Center(
child: ElevatedButton(
child: const Text('Press me'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) => const Text('BottomSheet'),
);
},
),
);
}),
),
));
expect(find.text('BottomSheet'), findsNothing);
await tester.tap(find.text('Press me'));
await tester.pumpAndSettle();
expect(find.text('BottomSheet'), findsOneWidget);
expect(tester.getRect(find.text('BottomSheet')),
const Rect.fromLTRB(0, 586, 800, 600));
});
testWidgets('Theme constraints used for bottomSheet property', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
bottomSheetTheme: const BottomSheetThemeData(
constraints: BoxConstraints(maxWidth: 80),
)
),
home: const Scaffold(
body: Center(child: Text('body')),
bottomSheet: Text('BottomSheet'),
),
));
expect(find.text('BottomSheet'), findsOneWidget);
// Should be centered and only 80dp wide
expect(tester.getRect(find.text('BottomSheet')),
const Rect.fromLTRB(360, 558, 440, 600));
});
testWidgets('Theme constraints used for showBottomSheet', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
bottomSheetTheme: const BottomSheetThemeData(
constraints: BoxConstraints(maxWidth: 80),
)
),
home: Scaffold(
body: Builder(builder: (BuildContext context) {
return Center(
child: ElevatedButton(
child: const Text('Press me'),
onPressed: () {
Scaffold.of(context).showBottomSheet<void>(
(BuildContext context) => const Text('BottomSheet')
);
},
),
);
}),
),
));
expect(find.text('BottomSheet'), findsNothing);
await tester.tap(find.text('Press me'));
await tester.pumpAndSettle();
expect(find.text('BottomSheet'), findsOneWidget);
// Should be centered and only 80dp wide
expect(tester.getRect(find.text('BottomSheet')),
const Rect.fromLTRB(360, 558, 440, 600));
});
testWidgets('Theme constraints used for showModalBottomSheet', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
bottomSheetTheme: const BottomSheetThemeData(
constraints: BoxConstraints(maxWidth: 80),
)
),
home: Scaffold(
body: Builder(builder: (BuildContext context) {
return Center(
child: ElevatedButton(
child: const Text('Press me'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) => const Text('BottomSheet'),
);
},
),
);
}),
),
));
expect(find.text('BottomSheet'), findsNothing);
await tester.tap(find.text('Press me'));
await tester.pumpAndSettle();
expect(find.text('BottomSheet'), findsOneWidget);
// Should be centered and only 80dp wide
expect(tester.getRect(find.text('BottomSheet')),
const Rect.fromLTRB(360, 558, 440, 600));
});
testWidgets('constraints param overrides theme for showBottomSheet', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
bottomSheetTheme: const BottomSheetThemeData(
constraints: BoxConstraints(maxWidth: 80),
)
),
home: Scaffold(
body: Builder(builder: (BuildContext context) {
return Center(
child: ElevatedButton(
child: const Text('Press me'),
onPressed: () {
Scaffold.of(context).showBottomSheet<void>(
(BuildContext context) => const Text('BottomSheet'),
constraints: const BoxConstraints(maxWidth: 100),
);
},
),
);
}),
),
));
expect(find.text('BottomSheet'), findsNothing);
await tester.tap(find.text('Press me'));
await tester.pumpAndSettle();
expect(find.text('BottomSheet'), findsOneWidget);
// Should be centered and only 100dp wide instead of 80dp wide
expect(tester.getRect(find.text('BottomSheet')),
const Rect.fromLTRB(350, 572, 450, 600));
});
testWidgets('constraints param overrides theme for showModalBottomSheet', (WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(
theme: ThemeData(
bottomSheetTheme: const BottomSheetThemeData(
constraints: BoxConstraints(maxWidth: 80),
)
),
home: Scaffold(
body: Builder(builder: (BuildContext context) {
return Center(
child: ElevatedButton(
child: const Text('Press me'),
onPressed: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) => const Text('BottomSheet'),
constraints: const BoxConstraints(maxWidth: 100),
);
},
),
);
}),
),
));
expect(find.text('BottomSheet'), findsNothing);
await tester.tap(find.text('Press me'));
await tester.pumpAndSettle();
expect(find.text('BottomSheet'), findsOneWidget);
// Should be centered and only 100dp instead of 80dp wide
expect(tester.getRect(find.text('BottomSheet')),
const Rect.fromLTRB(350, 572, 450, 600));
});
});
} }
class _TestPage extends StatelessWidget { class _TestPage extends StatelessWidget {
......
...@@ -18,6 +18,7 @@ void main() { ...@@ -18,6 +18,7 @@ void main() {
expect(bottomSheetTheme.elevation, null); expect(bottomSheetTheme.elevation, null);
expect(bottomSheetTheme.shape, null); expect(bottomSheetTheme.shape, null);
expect(bottomSheetTheme.clipBehavior, null); expect(bottomSheetTheme.clipBehavior, null);
expect(bottomSheetTheme.constraints, null);
}); });
testWidgets('Default BottomSheetThemeData debugFillProperties', (WidgetTester tester) async { testWidgets('Default BottomSheetThemeData debugFillProperties', (WidgetTester tester) async {
...@@ -39,6 +40,7 @@ void main() { ...@@ -39,6 +40,7 @@ void main() {
elevation: 2.0, elevation: 2.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(2.0)),
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
constraints: const BoxConstraints(minWidth: 200, maxWidth: 640),
).debugFillProperties(builder); ).debugFillProperties(builder);
final List<String> description = builder.properties final List<String> description = builder.properties
...@@ -51,6 +53,7 @@ void main() { ...@@ -51,6 +53,7 @@ void main() {
'elevation: 2.0', 'elevation: 2.0',
'shape: RoundedRectangleBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none), BorderRadius.circular(2.0))', 'shape: RoundedRectangleBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none), BorderRadius.circular(2.0))',
'clipBehavior: Clip.antiAlias', 'clipBehavior: Clip.antiAlias',
'constraints: BoxConstraints(200.0<=w<=640.0, 0.0<=h<=Infinity)',
]); ]);
}); });
......
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