🚀 Expose scrollControlDisabledMaxHeightRatio
to the modal bottom sheet (#129688)
Adding the `scrollControlDisabledMaxHeightRatio` parameter for modal bottom sheet widgets, and using the default value `9.0 / 16.0` to avoid breaking. Resolves #129690.
This commit is contained in:
parent
300c5d8285
commit
9f374f12ea
@ -26,6 +26,7 @@ const Duration _bottomSheetExitDuration = Duration(milliseconds: 200);
|
||||
const Curve _modalBottomSheetCurve = decelerateEasing;
|
||||
const double _minFlingVelocity = 700.0;
|
||||
const double _closeProgressThreshold = 0.5;
|
||||
const double _defaultScrollControlDisabledMaxHeightRatio = 9.0 / 16.0;
|
||||
|
||||
/// A callback for when the user begins dragging the bottom sheet.
|
||||
///
|
||||
@ -471,24 +472,26 @@ class _DragHandle extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _BottomSheetLayoutWithSizeListener extends SingleChildRenderObjectWidget {
|
||||
|
||||
const _BottomSheetLayoutWithSizeListener({
|
||||
required this.onChildSizeChanged,
|
||||
required this.animationValue,
|
||||
required this.isScrollControlled,
|
||||
required this.onChildSizeChanged,
|
||||
required this.scrollControlDisabledMaxHeightRatio,
|
||||
super.child,
|
||||
});
|
||||
|
||||
final _SizeChangeCallback<Size> onChildSizeChanged;
|
||||
final double animationValue;
|
||||
final bool isScrollControlled;
|
||||
final _SizeChangeCallback<Size> onChildSizeChanged;
|
||||
final double scrollControlDisabledMaxHeightRatio;
|
||||
|
||||
@override
|
||||
_RenderBottomSheetLayoutWithSizeListener createRenderObject(BuildContext context) {
|
||||
return _RenderBottomSheetLayoutWithSizeListener(
|
||||
onChildSizeChanged: onChildSizeChanged,
|
||||
animationValue: animationValue,
|
||||
isScrollControlled: isScrollControlled,
|
||||
onChildSizeChanged: onChildSizeChanged,
|
||||
scrollControlDisabledMaxHeightRatio: scrollControlDisabledMaxHeightRatio,
|
||||
);
|
||||
}
|
||||
|
||||
@ -497,6 +500,7 @@ class _BottomSheetLayoutWithSizeListener extends SingleChildRenderObjectWidget {
|
||||
renderObject.onChildSizeChanged = onChildSizeChanged;
|
||||
renderObject.animationValue = animationValue;
|
||||
renderObject.isScrollControlled = isScrollControlled;
|
||||
renderObject.scrollControlDisabledMaxHeightRatio = scrollControlDisabledMaxHeightRatio;
|
||||
}
|
||||
}
|
||||
|
||||
@ -506,9 +510,11 @@ class _RenderBottomSheetLayoutWithSizeListener extends RenderShiftedBox {
|
||||
required _SizeChangeCallback<Size> onChildSizeChanged,
|
||||
required double animationValue,
|
||||
required bool isScrollControlled,
|
||||
}) : _animationValue = animationValue,
|
||||
required double scrollControlDisabledMaxHeightRatio,
|
||||
}) : _onChildSizeChanged = onChildSizeChanged,
|
||||
_animationValue = animationValue,
|
||||
_isScrollControlled = isScrollControlled,
|
||||
_onChildSizeChanged = onChildSizeChanged,
|
||||
_scrollControlDisabledMaxHeightRatio = scrollControlDisabledMaxHeightRatio,
|
||||
super(child);
|
||||
|
||||
Size _lastSize = Size.zero;
|
||||
@ -546,6 +552,17 @@ class _RenderBottomSheetLayoutWithSizeListener extends RenderShiftedBox {
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
double get scrollControlDisabledMaxHeightRatio => _scrollControlDisabledMaxHeightRatio;
|
||||
double _scrollControlDisabledMaxHeightRatio;
|
||||
set scrollControlDisabledMaxHeightRatio(double newValue) {
|
||||
if (_scrollControlDisabledMaxHeightRatio == newValue) {
|
||||
return;
|
||||
}
|
||||
|
||||
_scrollControlDisabledMaxHeightRatio = newValue;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
Size _getSize(BoxConstraints constraints) {
|
||||
return constraints.constrain(constraints.biggest);
|
||||
}
|
||||
@ -591,13 +608,13 @@ class _RenderBottomSheetLayoutWithSizeListener extends RenderShiftedBox {
|
||||
return _getSize(constraints);
|
||||
}
|
||||
|
||||
BoxConstraints _getConstraintsForChild(BoxConstraints constraints) {
|
||||
BoxConstraints _getConstraintsForChild(BoxConstraints constraints) {
|
||||
return BoxConstraints(
|
||||
minWidth: constraints.maxWidth,
|
||||
maxWidth: constraints.maxWidth,
|
||||
maxHeight: isScrollControlled
|
||||
? constraints.maxHeight
|
||||
: constraints.maxHeight * 9.0 / 16.0,
|
||||
? constraints.maxHeight
|
||||
: constraints.maxHeight * scrollControlDisabledMaxHeightRatio,
|
||||
);
|
||||
}
|
||||
|
||||
@ -634,12 +651,14 @@ class _ModalBottomSheet<T> extends StatefulWidget {
|
||||
this.clipBehavior,
|
||||
this.constraints,
|
||||
this.isScrollControlled = false,
|
||||
this.scrollControlDisabledMaxHeightRatio = _defaultScrollControlDisabledMaxHeightRatio,
|
||||
this.enableDrag = true,
|
||||
this.showDragHandle = false,
|
||||
});
|
||||
|
||||
final ModalBottomSheetRoute<T> route;
|
||||
final bool isScrollControlled;
|
||||
final double scrollControlDisabledMaxHeightRatio;
|
||||
final Color? backgroundColor;
|
||||
final double? elevation;
|
||||
final ShapeBorder? shape;
|
||||
@ -730,6 +749,7 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
|
||||
},
|
||||
animationValue: animationValue,
|
||||
isScrollControlled: widget.isScrollControlled,
|
||||
scrollControlDisabledMaxHeightRatio: widget.scrollControlDisabledMaxHeightRatio,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
@ -815,6 +835,7 @@ class ModalBottomSheetRoute<T> extends PopupRoute<T> {
|
||||
this.enableDrag = true,
|
||||
this.showDragHandle,
|
||||
required this.isScrollControlled,
|
||||
this.scrollControlDisabledMaxHeightRatio = _defaultScrollControlDisabledMaxHeightRatio,
|
||||
super.settings,
|
||||
this.transitionAnimationController,
|
||||
this.anchorPoint,
|
||||
@ -842,6 +863,13 @@ class ModalBottomSheetRoute<T> extends PopupRoute<T> {
|
||||
/// to have the bottom sheet be draggable.
|
||||
final bool isScrollControlled;
|
||||
|
||||
/// The max height constraint ratio for the bottom sheet
|
||||
/// when [isScrollControlled] set to false,
|
||||
/// no ratio will be applied when [isScrollControlled] set to true.
|
||||
///
|
||||
/// Defaults to 9 / 16.
|
||||
final double scrollControlDisabledMaxHeightRatio;
|
||||
|
||||
/// The bottom sheet's background color.
|
||||
///
|
||||
/// Defines the bottom sheet's [Material.color].
|
||||
@ -1026,6 +1054,7 @@ class ModalBottomSheetRoute<T> extends PopupRoute<T> {
|
||||
clipBehavior: clipBehavior,
|
||||
constraints: constraints,
|
||||
isScrollControlled: isScrollControlled,
|
||||
scrollControlDisabledMaxHeightRatio: scrollControlDisabledMaxHeightRatio,
|
||||
enableDrag: enableDrag,
|
||||
showDragHandle: showDragHandle ?? (enableDrag && (sheetTheme.showDragHandle ?? false)),
|
||||
);
|
||||
@ -1192,6 +1221,7 @@ Future<T?> showModalBottomSheet<T>({
|
||||
BoxConstraints? constraints,
|
||||
Color? barrierColor,
|
||||
bool isScrollControlled = false,
|
||||
double scrollControlDisabledMaxHeightRatio = _defaultScrollControlDisabledMaxHeightRatio,
|
||||
bool useRootNavigator = false,
|
||||
bool isDismissible = true,
|
||||
bool enableDrag = true,
|
||||
@ -1210,6 +1240,7 @@ Future<T?> showModalBottomSheet<T>({
|
||||
builder: builder,
|
||||
capturedThemes: InheritedTheme.capture(from: context, to: navigator.context),
|
||||
isScrollControlled: isScrollControlled,
|
||||
scrollControlDisabledMaxHeightRatio: scrollControlDisabledMaxHeightRatio,
|
||||
barrierLabel: barrierLabel ?? localizations.scrimLabel,
|
||||
barrierOnTapHint: localizations.scrimOnTapHint(localizations.bottomSheetLabel),
|
||||
backgroundColor: backgroundColor,
|
||||
|
@ -1789,7 +1789,7 @@ void main() {
|
||||
});
|
||||
|
||||
group('constraints', () {
|
||||
testWidgets('default constraints are max width 640 in material 3', (WidgetTester tester) async {
|
||||
testWidgets('default constraints are max width 640 in material 3', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
theme: ThemeData.light(useMaterial3: true),
|
||||
@ -2045,6 +2045,58 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
group('scrollControlDisabledMaxHeightRatio', () {
|
||||
Future<void> test(
|
||||
WidgetTester tester,
|
||||
bool isScrollControlled,
|
||||
double scrollControlDisabledMaxHeightRatio,
|
||||
) 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,
|
||||
isScrollControlled: isScrollControlled,
|
||||
scrollControlDisabledMaxHeightRatio: scrollControlDisabledMaxHeightRatio,
|
||||
builder: (BuildContext context) => const SizedBox.expand(
|
||||
child: Text('BottomSheet'),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.tap(find.text('Press me'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(
|
||||
tester.getRect(find.text('BottomSheet')),
|
||||
Rect.fromLTRB(
|
||||
80,
|
||||
600 * (isScrollControlled ? 0 : (1 - scrollControlDisabledMaxHeightRatio)),
|
||||
720,
|
||||
600,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
testWidgets('works at 9 / 16', (WidgetTester tester) {
|
||||
return test(tester, false, 9.0 / 16.0);
|
||||
});
|
||||
testWidgets('works at 8 / 16', (WidgetTester tester) {
|
||||
return test(tester, false, 8.0 / 16.0);
|
||||
});
|
||||
testWidgets('works at isScrollControlled', (WidgetTester tester) {
|
||||
return test(tester, true, 8.0 / 16.0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
group('showModalBottomSheet modalBarrierDismissLabel', () {
|
||||
|
Loading…
x
Reference in New Issue
Block a user