Update Material 3 bottom sheet (#122445)
* M3 bottomsheet * Update bottom_sheet.dart * Update bottom_sheet.dart * Update bottom_sheet.dart * Update bottom_sheet.dart * Update bottom_sheet.dart * Update bottom_sheet.dart * Update bottom_sheet.dart * Update bottom_sheet.dart * Update bottom_sheet.dart * Update bottom_sheet.dart * Update packages/flutter/lib/src/material/bottom_sheet.dart Co-authored-by: Pierre-Louis <6655696+guidezpl@users.noreply.github.com> * Update packages/flutter/lib/src/material/bottom_sheet.dart Co-authored-by: Pierre-Louis <6655696+guidezpl@users.noreply.github.com> * Update packages/flutter/lib/src/material/bottom_sheet.dart Co-authored-by: Pierre-Louis <6655696+guidezpl@users.noreply.github.com> * Update packages/flutter/lib/src/material/bottom_sheet.dart Co-authored-by: Pierre-Louis <6655696+guidezpl@users.noreply.github.com> * Update packages/flutter/lib/src/material/bottom_sheet.dart Co-authored-by: Pierre-Louis <6655696+guidezpl@users.noreply.github.com> * Update packages/flutter/lib/src/material/bottom_sheet.dart Co-authored-by: Pierre-Louis <6655696+guidezpl@users.noreply.github.com> * Update bottom_sheet.dart Update bottom_sheet_test.dart Update bottom_sheet.dart * showDragHandle defaults to false * fix test --------- Co-authored-by: Pierre-Louis <6655696+guidezpl@users.noreply.github.com>
This commit is contained in:
parent
d58be8c7c8
commit
9fc1fd15f6
@ -17,6 +17,7 @@ class _${blockName}DefaultsM3 extends BottomSheetThemeData {
|
|||||||
elevation: ${elevation("md.comp.sheet.bottom.docked.standard.container")},
|
elevation: ${elevation("md.comp.sheet.bottom.docked.standard.container")},
|
||||||
modalElevation: ${elevation("md.comp.sheet.bottom.docked.modal.container")},
|
modalElevation: ${elevation("md.comp.sheet.bottom.docked.modal.container")},
|
||||||
shape: ${shape("md.comp.sheet.bottom.docked.container")},
|
shape: ${shape("md.comp.sheet.bottom.docked.container")},
|
||||||
|
constraints: const BoxConstraints(maxWidth: 640),
|
||||||
);
|
);
|
||||||
|
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
@ -30,6 +31,12 @@ class _${blockName}DefaultsM3 extends BottomSheetThemeData {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Color? get shadowColor => Colors.transparent;
|
Color? get shadowColor => Colors.transparent;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color? get dragHandleColor => ${componentColor("md.comp.sheet.bottom.docked.drag-handle")};
|
||||||
|
|
||||||
|
@override
|
||||||
|
Size? get dragHandleSize => ${size("md.comp.sheet.bottom.docked.drag-handle")};
|
||||||
}
|
}
|
||||||
''';
|
''';
|
||||||
}
|
}
|
||||||
|
@ -5,16 +5,19 @@
|
|||||||
import 'dart:ui' show lerpDouble;
|
import 'dart:ui' show lerpDouble;
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/rendering.dart';
|
import 'package:flutter/rendering.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
import 'bottom_sheet_theme.dart';
|
import 'bottom_sheet_theme.dart';
|
||||||
import 'color_scheme.dart';
|
import 'color_scheme.dart';
|
||||||
import 'colors.dart';
|
import 'colors.dart';
|
||||||
|
import 'constants.dart';
|
||||||
import 'curves.dart';
|
import 'curves.dart';
|
||||||
import 'debug.dart';
|
import 'debug.dart';
|
||||||
import 'material.dart';
|
import 'material.dart';
|
||||||
import 'material_localizations.dart';
|
import 'material_localizations.dart';
|
||||||
|
import 'material_state.dart';
|
||||||
import 'scaffold.dart';
|
import 'scaffold.dart';
|
||||||
import 'theme.dart';
|
import 'theme.dart';
|
||||||
|
|
||||||
@ -65,7 +68,8 @@ typedef BottomSheetDragEndHandler = void Function(
|
|||||||
/// sheet.
|
/// sheet.
|
||||||
/// * [BottomSheetThemeData], which can be used to customize the default
|
/// * [BottomSheetThemeData], which can be used to customize the default
|
||||||
/// bottom sheet property values.
|
/// bottom sheet property values.
|
||||||
/// * <https://material.io/design/components/sheets-bottom.html>
|
/// * The Material 2 spec at <https://m2.material.io/components/sheets-bottom>.
|
||||||
|
/// * The Material 3 spec at <https://m3.material.io/components/bottom-sheets/overview>.
|
||||||
class BottomSheet extends StatefulWidget {
|
class BottomSheet extends StatefulWidget {
|
||||||
/// Creates a bottom sheet.
|
/// Creates a bottom sheet.
|
||||||
///
|
///
|
||||||
@ -76,6 +80,9 @@ class BottomSheet extends StatefulWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
this.animationController,
|
this.animationController,
|
||||||
this.enableDrag = true,
|
this.enableDrag = true,
|
||||||
|
this.showDragHandle,
|
||||||
|
this.dragHandleColor,
|
||||||
|
this.dragHandleSize,
|
||||||
this.onDragStart,
|
this.onDragStart,
|
||||||
this.onDragEnd,
|
this.onDragEnd,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
@ -111,9 +118,34 @@ class BottomSheet extends StatefulWidget {
|
|||||||
/// If true, the bottom sheet can be dragged up and down and dismissed by
|
/// If true, the bottom sheet can be dragged up and down and dismissed by
|
||||||
/// swiping downwards.
|
/// swiping downwards.
|
||||||
///
|
///
|
||||||
|
/// If [showDragHandle] is true, this only applies to the content below the drag handle,
|
||||||
|
/// because the drag handle is always draggable.
|
||||||
|
///
|
||||||
/// Default is true.
|
/// Default is true.
|
||||||
final bool enableDrag;
|
final bool enableDrag;
|
||||||
|
|
||||||
|
/// Specifies whether a drag handle is shown.
|
||||||
|
///
|
||||||
|
/// The drag handle appears at the top of the bottom sheet. The default color is
|
||||||
|
/// [ColorScheme.onSurfaceVariant] with an opacity of 0.4 and can be customized
|
||||||
|
/// using [dragHandleColor]. The default size is `Size(32,4)` and can be customized
|
||||||
|
/// with [dragHandleSize].
|
||||||
|
///
|
||||||
|
/// If null, then the value of [BottomSheetThemeData.showDragHandle] is used. If
|
||||||
|
/// that is also null, defaults to false.
|
||||||
|
final bool? showDragHandle;
|
||||||
|
|
||||||
|
/// The bottom sheet drag handle's color.
|
||||||
|
///
|
||||||
|
/// Defaults to [BottomSheetThemeData.dragHandleColor].
|
||||||
|
/// If that is also null, defaults to [ColorScheme.onSurfaceVariant]
|
||||||
|
/// with an opacity of 0.4.
|
||||||
|
final Color? dragHandleColor;
|
||||||
|
|
||||||
|
/// Defaults to [BottomSheetThemeData.dragHandleSize].
|
||||||
|
/// If that is also null, defaults to Size(32, 4).
|
||||||
|
final Size? dragHandleSize;
|
||||||
|
|
||||||
/// Called when the user begins dragging the bottom sheet vertically, if
|
/// Called when the user begins dragging the bottom sheet vertically, if
|
||||||
/// [enableDrag] is true.
|
/// [enableDrag] is true.
|
||||||
///
|
///
|
||||||
@ -222,14 +254,19 @@ class _BottomSheetState extends State<BottomSheet> {
|
|||||||
|
|
||||||
bool get _dismissUnderway => widget.animationController!.status == AnimationStatus.reverse;
|
bool get _dismissUnderway => widget.animationController!.status == AnimationStatus.reverse;
|
||||||
|
|
||||||
|
Set<MaterialState> dragHandleMaterialState = <MaterialState>{};
|
||||||
|
|
||||||
void _handleDragStart(DragStartDetails details) {
|
void _handleDragStart(DragStartDetails details) {
|
||||||
|
setState(() {
|
||||||
|
dragHandleMaterialState.add(MaterialState.dragged);
|
||||||
|
});
|
||||||
widget.onDragStart?.call(details);
|
widget.onDragStart?.call(details);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleDragUpdate(DragUpdateDetails details) {
|
void _handleDragUpdate(DragUpdateDetails details) {
|
||||||
assert(
|
assert(
|
||||||
widget.enableDrag && widget.animationController != null,
|
(widget.enableDrag || (widget.showDragHandle?? false)) && widget.animationController != null,
|
||||||
"'BottomSheet.animationController' can not be null when 'BottomSheet.enableDrag' is true. "
|
"'BottomSheet.animationController' cannot be null when 'BottomSheet.enableDrag' or 'BottomSheet.showDragHandle' is true. "
|
||||||
"Use 'BottomSheet.createAnimationController' to create one, or provide another AnimationController.",
|
"Use 'BottomSheet.createAnimationController' to create one, or provide another AnimationController.",
|
||||||
);
|
);
|
||||||
if (_dismissUnderway) {
|
if (_dismissUnderway) {
|
||||||
@ -240,13 +277,16 @@ class _BottomSheetState extends State<BottomSheet> {
|
|||||||
|
|
||||||
void _handleDragEnd(DragEndDetails details) {
|
void _handleDragEnd(DragEndDetails details) {
|
||||||
assert(
|
assert(
|
||||||
widget.enableDrag && widget.animationController != null,
|
(widget.enableDrag || (widget.showDragHandle?? false)) && widget.animationController != null,
|
||||||
"'BottomSheet.animationController' can not be null when 'BottomSheet.enableDrag' is true. "
|
"'BottomSheet.animationController' cannot be null when 'BottomSheet.enableDrag' or 'BottomSheet.showDragHandle' is true. "
|
||||||
"Use 'BottomSheet.createAnimationController' to create one, or provide another AnimationController.",
|
"Use 'BottomSheet.createAnimationController' to create one, or provide another AnimationController.",
|
||||||
);
|
);
|
||||||
if (_dismissUnderway) {
|
if (_dismissUnderway) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
setState(() {
|
||||||
|
dragHandleMaterialState.remove(MaterialState.dragged);
|
||||||
|
});
|
||||||
bool isClosing = false;
|
bool isClosing = false;
|
||||||
if (details.velocity.pixelsPerSecond.dy > _minFlingVelocity) {
|
if (details.velocity.pixelsPerSecond.dy > _minFlingVelocity) {
|
||||||
final double flingVelocity = -details.velocity.pixelsPerSecond.dy / _childHeight;
|
final double flingVelocity = -details.velocity.pixelsPerSecond.dy / _childHeight;
|
||||||
@ -282,17 +322,55 @@ class _BottomSheetState extends State<BottomSheet> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _handleDragHandleHover(bool hovering) {
|
||||||
|
if (hovering != dragHandleMaterialState.contains(MaterialState.hovered)) {
|
||||||
|
setState(() {
|
||||||
|
if(hovering){
|
||||||
|
dragHandleMaterialState.add(MaterialState.hovered);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
dragHandleMaterialState.remove(MaterialState.hovered);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@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 BottomSheetThemeData defaults = Theme.of(context).useMaterial3 ? _BottomSheetDefaultsM3(context) : const BottomSheetThemeData();
|
final bool useMaterial3 = Theme.of(context).useMaterial3;
|
||||||
final BoxConstraints? constraints = widget.constraints ?? bottomSheetTheme.constraints;
|
final BottomSheetThemeData defaults = useMaterial3 ? _BottomSheetDefaultsM3(context) : const BottomSheetThemeData();
|
||||||
|
final BoxConstraints? constraints = widget.constraints ?? bottomSheetTheme.constraints ?? defaults.constraints;
|
||||||
final Color? color = widget.backgroundColor ?? bottomSheetTheme.backgroundColor ?? defaults.backgroundColor;
|
final Color? color = widget.backgroundColor ?? bottomSheetTheme.backgroundColor ?? defaults.backgroundColor;
|
||||||
final Color? surfaceTintColor = bottomSheetTheme.surfaceTintColor ?? defaults.surfaceTintColor;
|
final Color? surfaceTintColor = bottomSheetTheme.surfaceTintColor ?? defaults.surfaceTintColor;
|
||||||
final Color? shadowColor = widget.shadowColor ?? bottomSheetTheme.shadowColor ?? defaults.shadowColor;
|
final Color? shadowColor = widget.shadowColor ?? bottomSheetTheme.shadowColor ?? defaults.shadowColor;
|
||||||
final double elevation = widget.elevation ?? bottomSheetTheme.elevation ?? defaults.elevation ?? 0;
|
final double elevation = widget.elevation ?? bottomSheetTheme.elevation ?? defaults.elevation ?? 0;
|
||||||
final ShapeBorder? shape = widget.shape ?? bottomSheetTheme.shape ?? defaults.shape;
|
final ShapeBorder? shape = widget.shape ?? bottomSheetTheme.shape ?? defaults.shape;
|
||||||
final Clip clipBehavior = widget.clipBehavior ?? bottomSheetTheme.clipBehavior ?? Clip.none;
|
final Clip clipBehavior = widget.clipBehavior ?? bottomSheetTheme.clipBehavior ?? Clip.none;
|
||||||
|
final bool showDragHandle = widget.showDragHandle ?? (widget.enableDrag && (bottomSheetTheme.showDragHandle ?? false));
|
||||||
|
|
||||||
|
Widget? dragHandle;
|
||||||
|
if (showDragHandle){
|
||||||
|
dragHandle = _DragHandle(
|
||||||
|
onSemanticsTap: widget.onClosing,
|
||||||
|
handleHover: _handleDragHandleHover,
|
||||||
|
materialState: dragHandleMaterialState,
|
||||||
|
dragHandleColor: widget.dragHandleColor,
|
||||||
|
dragHandleSize: widget.dragHandleSize,
|
||||||
|
);
|
||||||
|
// Only add [GestureDetector] to the drag handle when the rest of the
|
||||||
|
// bottom sheet is not draggable. If the whole bottom sheet is draggable,
|
||||||
|
// no need to add it.
|
||||||
|
if(!widget.enableDrag) {
|
||||||
|
dragHandle = GestureDetector(
|
||||||
|
onVerticalDragStart: _handleDragStart,
|
||||||
|
onVerticalDragUpdate: _handleDragUpdate,
|
||||||
|
onVerticalDragEnd: _handleDragEnd,
|
||||||
|
excludeFromSemantics: true,
|
||||||
|
child: dragHandle,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Widget bottomSheet = Material(
|
Widget bottomSheet = Material(
|
||||||
key: _childKey,
|
key: _childKey,
|
||||||
@ -304,7 +382,18 @@ class _BottomSheetState extends State<BottomSheet> {
|
|||||||
clipBehavior: clipBehavior,
|
clipBehavior: clipBehavior,
|
||||||
child: NotificationListener<DraggableScrollableNotification>(
|
child: NotificationListener<DraggableScrollableNotification>(
|
||||||
onNotification: extentChanged,
|
onNotification: extentChanged,
|
||||||
child: widget.builder(context),
|
child: !showDragHandle
|
||||||
|
? widget.builder(context)
|
||||||
|
: Stack(
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
children: <Widget>[
|
||||||
|
dragHandle!,
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: kMinInteractiveDimension),
|
||||||
|
child: widget.builder(context),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -335,6 +424,55 @@ class _BottomSheetState extends State<BottomSheet> {
|
|||||||
|
|
||||||
typedef _SizeChangeCallback<Size> = void Function(Size);
|
typedef _SizeChangeCallback<Size> = void Function(Size);
|
||||||
|
|
||||||
|
class _DragHandle extends StatelessWidget {
|
||||||
|
const _DragHandle({
|
||||||
|
required this.onSemanticsTap,
|
||||||
|
required this.handleHover,
|
||||||
|
required this.materialState,
|
||||||
|
this.dragHandleColor,
|
||||||
|
this.dragHandleSize,
|
||||||
|
});
|
||||||
|
|
||||||
|
final VoidCallback? onSemanticsTap;
|
||||||
|
final Function(bool) handleHover;
|
||||||
|
final Set<MaterialState> materialState;
|
||||||
|
final Color? dragHandleColor;
|
||||||
|
final Size? dragHandleSize;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final BottomSheetThemeData bottomSheetTheme = Theme.of(context).bottomSheetTheme;
|
||||||
|
final BottomSheetThemeData m3Defaults = _BottomSheetDefaultsM3(context);
|
||||||
|
final Size handleSize = dragHandleSize ?? bottomSheetTheme.dragHandleSize ?? m3Defaults.dragHandleSize!;
|
||||||
|
|
||||||
|
return MouseRegion(
|
||||||
|
onEnter: (PointerEnterEvent event) => handleHover(true),
|
||||||
|
onExit: (PointerExitEvent event) => handleHover(false),
|
||||||
|
child: Semantics(
|
||||||
|
label: MaterialLocalizations.of(context).modalBarrierDismissLabel,
|
||||||
|
container: true,
|
||||||
|
onTap: onSemanticsTap,
|
||||||
|
child: SizedBox(
|
||||||
|
height: kMinInteractiveDimension,
|
||||||
|
width: kMinInteractiveDimension,
|
||||||
|
child: Center(
|
||||||
|
child: Container(
|
||||||
|
height: handleSize.height,
|
||||||
|
width: handleSize.width,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(handleSize.height/2),
|
||||||
|
color: MaterialStateProperty.resolveAs<Color?>(dragHandleColor, materialState)
|
||||||
|
?? MaterialStateProperty.resolveAs<Color?>(bottomSheetTheme.dragHandleColor, materialState)
|
||||||
|
?? m3Defaults.dragHandleColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _BottomSheetLayoutWithSizeListener extends SingleChildRenderObjectWidget {
|
class _BottomSheetLayoutWithSizeListener extends SingleChildRenderObjectWidget {
|
||||||
|
|
||||||
const _BottomSheetLayoutWithSizeListener({
|
const _BottomSheetLayoutWithSizeListener({
|
||||||
@ -500,6 +638,7 @@ class _ModalBottomSheet<T> extends StatefulWidget {
|
|||||||
this.constraints,
|
this.constraints,
|
||||||
this.isScrollControlled = false,
|
this.isScrollControlled = false,
|
||||||
this.enableDrag = true,
|
this.enableDrag = true,
|
||||||
|
this.showDragHandle = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
final ModalBottomSheetRoute<T> route;
|
final ModalBottomSheetRoute<T> route;
|
||||||
@ -510,6 +649,7 @@ class _ModalBottomSheet<T> extends StatefulWidget {
|
|||||||
final Clip? clipBehavior;
|
final Clip? clipBehavior;
|
||||||
final BoxConstraints? constraints;
|
final BoxConstraints? constraints;
|
||||||
final bool enableDrag;
|
final bool enableDrag;
|
||||||
|
final bool showDragHandle;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_ModalBottomSheetState<T> createState() => _ModalBottomSheetState<T>();
|
_ModalBottomSheetState<T> createState() => _ModalBottomSheetState<T>();
|
||||||
@ -571,6 +711,7 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
|
|||||||
clipBehavior: widget.clipBehavior,
|
clipBehavior: widget.clipBehavior,
|
||||||
constraints: widget.constraints,
|
constraints: widget.constraints,
|
||||||
enableDrag: widget.enableDrag,
|
enableDrag: widget.enableDrag,
|
||||||
|
showDragHandle: widget.showDragHandle,
|
||||||
onDragStart: handleDragStart,
|
onDragStart: handleDragStart,
|
||||||
onDragEnd: handleDragEnd,
|
onDragEnd: handleDragEnd,
|
||||||
),
|
),
|
||||||
@ -658,7 +799,8 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
|
|||||||
/// and then becomes scrollable once it reaches its maximum size.
|
/// and then becomes scrollable once it reaches its maximum size.
|
||||||
/// * [DisplayFeatureSubScreen], which documents the specifics of how
|
/// * [DisplayFeatureSubScreen], which documents the specifics of how
|
||||||
/// [DisplayFeature]s can split the screen into sub-screens.
|
/// [DisplayFeature]s can split the screen into sub-screens.
|
||||||
/// * <https://material.io/design/components/sheets-bottom.html#modal-bottom-sheet>
|
/// * The Material 2 spec at <https://m2.material.io/components/sheets-bottom>.
|
||||||
|
/// * The Material 3 spec at <https://m3.material.io/components/bottom-sheets/overview>.
|
||||||
class ModalBottomSheetRoute<T> extends PopupRoute<T> {
|
class ModalBottomSheetRoute<T> extends PopupRoute<T> {
|
||||||
/// A modal bottom sheet route.
|
/// A modal bottom sheet route.
|
||||||
ModalBottomSheetRoute({
|
ModalBottomSheetRoute({
|
||||||
@ -674,6 +816,7 @@ class ModalBottomSheetRoute<T> extends PopupRoute<T> {
|
|||||||
this.modalBarrierColor,
|
this.modalBarrierColor,
|
||||||
this.isDismissible = true,
|
this.isDismissible = true,
|
||||||
this.enableDrag = true,
|
this.enableDrag = true,
|
||||||
|
this.showDragHandle,
|
||||||
required this.isScrollControlled,
|
required this.isScrollControlled,
|
||||||
super.settings,
|
super.settings,
|
||||||
this.transitionAnimationController,
|
this.transitionAnimationController,
|
||||||
@ -773,9 +916,22 @@ class ModalBottomSheetRoute<T> extends PopupRoute<T> {
|
|||||||
/// If true, the bottom sheet can be dragged up and down and dismissed by
|
/// If true, the bottom sheet can be dragged up and down and dismissed by
|
||||||
/// swiping downwards.
|
/// swiping downwards.
|
||||||
///
|
///
|
||||||
|
/// This applies to the content below the drag handle, if showDragHandle is true.
|
||||||
|
///
|
||||||
/// Defaults is true.
|
/// Defaults is true.
|
||||||
final bool enableDrag;
|
final bool enableDrag;
|
||||||
|
|
||||||
|
/// Specifies whether a drag handle is shown.
|
||||||
|
///
|
||||||
|
/// The drag handle appears at the top of the bottom sheet. The default color is
|
||||||
|
/// [ColorScheme.onSurfaceVariant] with an opacity of 0.4 and can be customized
|
||||||
|
/// using dragHandleColor. The default size is `Size(32,4)` and can be customized
|
||||||
|
/// with dragHandleSize.
|
||||||
|
///
|
||||||
|
/// If null, then the value of [BottomSheetThemeData.showDragHandle] is used. If
|
||||||
|
/// that is also null, defaults to false.
|
||||||
|
final bool? showDragHandle;
|
||||||
|
|
||||||
/// The animation controller that controls the bottom sheet's entrance and
|
/// The animation controller that controls the bottom sheet's entrance and
|
||||||
/// exit animations.
|
/// exit animations.
|
||||||
///
|
///
|
||||||
@ -875,6 +1031,7 @@ class ModalBottomSheetRoute<T> extends PopupRoute<T> {
|
|||||||
constraints: constraints,
|
constraints: constraints,
|
||||||
isScrollControlled: isScrollControlled,
|
isScrollControlled: isScrollControlled,
|
||||||
enableDrag: enableDrag,
|
enableDrag: enableDrag,
|
||||||
|
showDragHandle: showDragHandle ?? (enableDrag && (sheetTheme.showDragHandle ?? false)),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -1023,7 +1180,8 @@ class _BottomSheetSuspendedCurve extends ParametricCurve<double> {
|
|||||||
/// and then becomes scrollable once it reaches its maximum size.
|
/// and then becomes scrollable once it reaches its maximum size.
|
||||||
/// * [DisplayFeatureSubScreen], which documents the specifics of how
|
/// * [DisplayFeatureSubScreen], which documents the specifics of how
|
||||||
/// [DisplayFeature]s can split the screen into sub-screens.
|
/// [DisplayFeature]s can split the screen into sub-screens.
|
||||||
/// * <https://material.io/design/components/sheets-bottom.html#modal-bottom-sheet>
|
/// * The Material 2 spec at <https://m2.material.io/components/sheets-bottom>.
|
||||||
|
/// * The Material 3 spec at <https://m3.material.io/components/bottom-sheets/overview>.
|
||||||
Future<T?> showModalBottomSheet<T>({
|
Future<T?> showModalBottomSheet<T>({
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required WidgetBuilder builder,
|
required WidgetBuilder builder,
|
||||||
@ -1037,6 +1195,7 @@ Future<T?> showModalBottomSheet<T>({
|
|||||||
bool useRootNavigator = false,
|
bool useRootNavigator = false,
|
||||||
bool isDismissible = true,
|
bool isDismissible = true,
|
||||||
bool enableDrag = true,
|
bool enableDrag = true,
|
||||||
|
bool? showDragHandle,
|
||||||
bool useSafeArea = false,
|
bool useSafeArea = false,
|
||||||
RouteSettings? routeSettings,
|
RouteSettings? routeSettings,
|
||||||
AnimationController? transitionAnimationController,
|
AnimationController? transitionAnimationController,
|
||||||
@ -1061,6 +1220,7 @@ Future<T?> showModalBottomSheet<T>({
|
|||||||
isDismissible: isDismissible,
|
isDismissible: isDismissible,
|
||||||
modalBarrierColor: barrierColor ?? Theme.of(context).bottomSheetTheme.modalBarrierColor,
|
modalBarrierColor: barrierColor ?? Theme.of(context).bottomSheetTheme.modalBarrierColor,
|
||||||
enableDrag: enableDrag,
|
enableDrag: enableDrag,
|
||||||
|
showDragHandle: showDragHandle,
|
||||||
settings: routeSettings,
|
settings: routeSettings,
|
||||||
transitionAnimationController: transitionAnimationController,
|
transitionAnimationController: transitionAnimationController,
|
||||||
anchorPoint: anchorPoint,
|
anchorPoint: anchorPoint,
|
||||||
@ -1111,7 +1271,8 @@ Future<T?> showModalBottomSheet<T>({
|
|||||||
/// * [showModalBottomSheet], which can be used to display a modal bottom
|
/// * [showModalBottomSheet], which can be used to display a modal bottom
|
||||||
/// sheet.
|
/// sheet.
|
||||||
/// * [Scaffold.of], for information about how to obtain the [BuildContext].
|
/// * [Scaffold.of], for information about how to obtain the [BuildContext].
|
||||||
/// * <https://material.io/design/components/sheets-bottom.html#standard-bottom-sheet>
|
/// * The Material 2 spec at <https://m2.material.io/components/sheets-bottom>.
|
||||||
|
/// * The Material 3 spec at <https://m3.material.io/components/bottom-sheets/overview>.
|
||||||
PersistentBottomSheetController<T> showBottomSheet<T>({
|
PersistentBottomSheetController<T> showBottomSheet<T>({
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
required WidgetBuilder builder,
|
required WidgetBuilder builder,
|
||||||
@ -1154,19 +1315,26 @@ class _BottomSheetDefaultsM3 extends BottomSheetThemeData {
|
|||||||
elevation: 1.0,
|
elevation: 1.0,
|
||||||
modalElevation: 1.0,
|
modalElevation: 1.0,
|
||||||
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(28.0))),
|
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.vertical(top: Radius.circular(28.0))),
|
||||||
|
constraints: const BoxConstraints(maxWidth: 640),
|
||||||
);
|
);
|
||||||
|
|
||||||
final BuildContext context;
|
final BuildContext context;
|
||||||
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
late final ColorScheme _colors = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color? get backgroundColor => _colors.surface;
|
Color get backgroundColor => _colors.surface;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color? get surfaceTintColor => _colors.surfaceTint;
|
Color get surfaceTintColor => _colors.surfaceTint;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Color? get shadowColor => Colors.transparent;
|
Color get shadowColor => Colors.transparent;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color get dragHandleColor => Theme.of(context).colorScheme.onSurfaceVariant.withOpacity(0.4);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Size get dragHandleSize => const Size(32, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// END GENERATED TOKEN PROPERTIES - BottomSheet
|
// END GENERATED TOKEN PROPERTIES - BottomSheet
|
||||||
|
@ -36,6 +36,9 @@ class BottomSheetThemeData with Diagnosticable {
|
|||||||
this.shadowColor,
|
this.shadowColor,
|
||||||
this.modalElevation,
|
this.modalElevation,
|
||||||
this.shape,
|
this.shape,
|
||||||
|
this.showDragHandle,
|
||||||
|
this.dragHandleColor,
|
||||||
|
this.dragHandleSize,
|
||||||
this.clipBehavior,
|
this.clipBehavior,
|
||||||
this.constraints,
|
this.constraints,
|
||||||
});
|
});
|
||||||
@ -80,6 +83,15 @@ class BottomSheetThemeData with Diagnosticable {
|
|||||||
/// [BottomSheet] is rectangular.
|
/// [BottomSheet] is rectangular.
|
||||||
final ShapeBorder? shape;
|
final ShapeBorder? shape;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomSheet.showDragHandle].
|
||||||
|
final bool? showDragHandle;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomSheet.dragHandleColor].
|
||||||
|
final Color? dragHandleColor;
|
||||||
|
|
||||||
|
/// Overrides the default value for [BottomSheet.dragHandleSize].
|
||||||
|
final Size? dragHandleSize;
|
||||||
|
|
||||||
/// Overrides the default value for [BottomSheet.clipBehavior].
|
/// Overrides the default value for [BottomSheet.clipBehavior].
|
||||||
///
|
///
|
||||||
/// If null, [BottomSheet] uses [Clip.none].
|
/// If null, [BottomSheet] uses [Clip.none].
|
||||||
@ -101,6 +113,9 @@ class BottomSheetThemeData with Diagnosticable {
|
|||||||
Color? shadowColor,
|
Color? shadowColor,
|
||||||
double? modalElevation,
|
double? modalElevation,
|
||||||
ShapeBorder? shape,
|
ShapeBorder? shape,
|
||||||
|
bool? showDragHandle,
|
||||||
|
Color? dragHandleColor,
|
||||||
|
Size? dragHandleSize,
|
||||||
Clip? clipBehavior,
|
Clip? clipBehavior,
|
||||||
BoxConstraints? constraints,
|
BoxConstraints? constraints,
|
||||||
}) {
|
}) {
|
||||||
@ -113,6 +128,9 @@ class BottomSheetThemeData with Diagnosticable {
|
|||||||
shadowColor: shadowColor ?? this.shadowColor,
|
shadowColor: shadowColor ?? this.shadowColor,
|
||||||
modalElevation: modalElevation ?? this.modalElevation,
|
modalElevation: modalElevation ?? this.modalElevation,
|
||||||
shape: shape ?? this.shape,
|
shape: shape ?? this.shape,
|
||||||
|
showDragHandle: showDragHandle ?? this.showDragHandle,
|
||||||
|
dragHandleColor: dragHandleColor ?? this.dragHandleColor,
|
||||||
|
dragHandleSize: dragHandleSize ?? this.dragHandleSize,
|
||||||
clipBehavior: clipBehavior ?? this.clipBehavior,
|
clipBehavior: clipBehavior ?? this.clipBehavior,
|
||||||
constraints: constraints ?? this.constraints,
|
constraints: constraints ?? this.constraints,
|
||||||
);
|
);
|
||||||
@ -136,6 +154,9 @@ class BottomSheetThemeData with Diagnosticable {
|
|||||||
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
|
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
|
||||||
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),
|
||||||
|
showDragHandle: t < 0.5 ? a?.showDragHandle : b?.showDragHandle,
|
||||||
|
dragHandleColor: Color.lerp(a?.dragHandleColor, b?.dragHandleColor, t),
|
||||||
|
dragHandleSize: Size.lerp(a?.dragHandleSize, b?.dragHandleSize, 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),
|
constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t),
|
||||||
);
|
);
|
||||||
@ -151,6 +172,9 @@ class BottomSheetThemeData with Diagnosticable {
|
|||||||
shadowColor,
|
shadowColor,
|
||||||
modalElevation,
|
modalElevation,
|
||||||
shape,
|
shape,
|
||||||
|
showDragHandle,
|
||||||
|
dragHandleColor,
|
||||||
|
dragHandleSize,
|
||||||
clipBehavior,
|
clipBehavior,
|
||||||
constraints,
|
constraints,
|
||||||
);
|
);
|
||||||
@ -172,6 +196,9 @@ class BottomSheetThemeData with Diagnosticable {
|
|||||||
&& other.modalBarrierColor == modalBarrierColor
|
&& other.modalBarrierColor == modalBarrierColor
|
||||||
&& other.modalElevation == modalElevation
|
&& other.modalElevation == modalElevation
|
||||||
&& other.shape == shape
|
&& other.shape == shape
|
||||||
|
&& other.showDragHandle == showDragHandle
|
||||||
|
&& other.dragHandleColor == dragHandleColor
|
||||||
|
&& other.dragHandleSize == dragHandleSize
|
||||||
&& other.clipBehavior == clipBehavior
|
&& other.clipBehavior == clipBehavior
|
||||||
&& other.constraints == constraints;
|
&& other.constraints == constraints;
|
||||||
}
|
}
|
||||||
@ -187,6 +214,9 @@ class BottomSheetThemeData with Diagnosticable {
|
|||||||
properties.add(ColorProperty('modalBarrierColor', modalBarrierColor, defaultValue: null));
|
properties.add(ColorProperty('modalBarrierColor', modalBarrierColor, defaultValue: null));
|
||||||
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<bool>('showDragHandle', showDragHandle, defaultValue: null));
|
||||||
|
properties.add(ColorProperty('dragHandleColor', dragHandleColor, defaultValue: null));
|
||||||
|
properties.add(DiagnosticsProperty<Size>('dragHandleSize', dragHandleSize, 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));
|
properties.add(DiagnosticsProperty<BoxConstraints>('constraints', constraints, defaultValue: null));
|
||||||
}
|
}
|
||||||
|
@ -2425,7 +2425,8 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
|
|||||||
/// * [showModalBottomSheet], which can be used to display a modal bottom
|
/// * [showModalBottomSheet], which can be used to display a modal bottom
|
||||||
/// sheet.
|
/// sheet.
|
||||||
/// * [Scaffold.of], for information about how to obtain the [ScaffoldState].
|
/// * [Scaffold.of], for information about how to obtain the [ScaffoldState].
|
||||||
/// * <https://material.io/design/components/sheets-bottom.html#standard-bottom-sheet>
|
/// * The Material 2 spec at <https://m2.material.io/components/sheets-bottom>.
|
||||||
|
/// * The Material 3 spec at <https://m3.material.io/components/bottom-sheets/overview>.
|
||||||
PersistentBottomSheetController<T> showBottomSheet<T>(
|
PersistentBottomSheetController<T> showBottomSheet<T>(
|
||||||
WidgetBuilder builder, {
|
WidgetBuilder builder, {
|
||||||
Color? backgroundColor,
|
Color? backgroundColor,
|
||||||
|
@ -1008,6 +1008,138 @@ void main() {
|
|||||||
semantics.dispose();
|
semantics.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('modal BottomSheet with drag handle has semantics', (WidgetTester tester) async {
|
||||||
|
final SemanticsTester semantics = SemanticsTester(tester);
|
||||||
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
theme: ThemeData.light(useMaterial3: true),
|
||||||
|
home: Scaffold(
|
||||||
|
key: scaffoldKey,
|
||||||
|
body: const Center(child: Text('body')),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
context: scaffoldKey.currentContext!,
|
||||||
|
showDragHandle: true,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return const Text('BottomSheet');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pump(); // bottom sheet show animation starts
|
||||||
|
await tester.pump(const Duration(seconds: 1)); // animation done
|
||||||
|
|
||||||
|
expect(semantics, hasSemantics(TestSemantics.root(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics.rootChild(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
label: 'Dialog',
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
flags: <SemanticsFlag>[
|
||||||
|
SemanticsFlag.scopesRoute,
|
||||||
|
SemanticsFlag.namesRoute,
|
||||||
|
],
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
label: 'BottomSheet',
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
actions: <SemanticsAction>[SemanticsAction.tap],
|
||||||
|
label: 'Dismiss',
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
TestSemantics(
|
||||||
|
children: <TestSemantics>[
|
||||||
|
TestSemantics(
|
||||||
|
actions: <SemanticsAction>[SemanticsAction.tap, SemanticsAction.dismiss],
|
||||||
|
label: 'Scrim',
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
), ignoreTransform: true, ignoreRect: true, ignoreId: true));
|
||||||
|
semantics.dispose();
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('Drag handle color can take MaterialStateProperty', (WidgetTester tester) async {
|
||||||
|
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
const Color defaultColor=Colors.blue;
|
||||||
|
const Color hoveringColor=Colors.green;
|
||||||
|
|
||||||
|
await tester.pumpWidget(MaterialApp(
|
||||||
|
theme: ThemeData.light(useMaterial3: true).copyWith(
|
||||||
|
bottomSheetTheme: BottomSheetThemeData(
|
||||||
|
dragHandleColor: MaterialStateColor.resolveWith((Set<MaterialState> states) {
|
||||||
|
if (states.contains(MaterialState.hovered)) {
|
||||||
|
return hoveringColor;
|
||||||
|
}
|
||||||
|
return defaultColor;
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
home: Scaffold(
|
||||||
|
key: scaffoldKey,
|
||||||
|
body: const Center(child: Text('body')),
|
||||||
|
),
|
||||||
|
));
|
||||||
|
|
||||||
|
|
||||||
|
showModalBottomSheet<void>(
|
||||||
|
context: scaffoldKey.currentContext!,
|
||||||
|
showDragHandle: true,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return const Text('BottomSheet');
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pump(); // bottom sheet show animation starts
|
||||||
|
await tester.pump(const Duration(seconds: 1)); // animation done
|
||||||
|
|
||||||
|
final Finder dragHandle = find.bySemanticsLabel('Dismiss');
|
||||||
|
expect(
|
||||||
|
tester.getSize(dragHandle),
|
||||||
|
const Size(48, 48),
|
||||||
|
);
|
||||||
|
final Offset center = tester.getCenter(dragHandle);
|
||||||
|
final Offset edge = tester.getTopLeft(dragHandle) - const Offset(1, 1);
|
||||||
|
|
||||||
|
// Shows default drag handle color
|
||||||
|
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse, pointer: 1);
|
||||||
|
await gesture.addPointer(location: edge);
|
||||||
|
await tester.pump();
|
||||||
|
BoxDecoration boxDecoration=tester.widget<Container>(find.descendant(
|
||||||
|
of: dragHandle,
|
||||||
|
matching: find.byWidgetPredicate((Widget widget) => widget is Container && widget.decoration != null),
|
||||||
|
)).decoration! as BoxDecoration;
|
||||||
|
expect(boxDecoration.color, defaultColor);
|
||||||
|
|
||||||
|
// Shows hovering drag handle color
|
||||||
|
await gesture.moveTo(center);
|
||||||
|
await tester.pump();
|
||||||
|
boxDecoration = tester.widget<Container>(find.descendant(
|
||||||
|
of: dragHandle,
|
||||||
|
matching: find.byWidgetPredicate((Widget widget) => widget is Container && widget.decoration != null),
|
||||||
|
)).decoration! as BoxDecoration;
|
||||||
|
|
||||||
|
expect(boxDecoration.color, hoveringColor);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('showModalBottomSheet does not use root Navigator by default', (WidgetTester tester) async {
|
testWidgets('showModalBottomSheet does not use root Navigator by default', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(MaterialApp(
|
await tester.pumpWidget(MaterialApp(
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
@ -1617,6 +1749,21 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
group('constraints', () {
|
group('constraints', () {
|
||||||
|
testWidgets('default constraints are max width 640 in material 3', (WidgetTester tester) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
theme: ThemeData.light(useMaterial3: true),
|
||||||
|
home: const MediaQuery(
|
||||||
|
data: MediaQueryData(size: Size(1000, 1000)),
|
||||||
|
child: Scaffold(
|
||||||
|
body: Center(child: Text('body')),
|
||||||
|
bottomSheet: Placeholder(fallbackWidth: 800),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
expect(tester.getSize(find.byType(Placeholder)).width, 640);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('No constraints by default for bottomSheet property', (WidgetTester tester) async {
|
testWidgets('No constraints by default for bottomSheet property', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(const MaterialApp(
|
await tester.pumpWidget(const MaterialApp(
|
||||||
|
@ -32,6 +32,8 @@ void main() {
|
|||||||
expect(bottomSheetTheme.shape, null);
|
expect(bottomSheetTheme.shape, null);
|
||||||
expect(bottomSheetTheme.clipBehavior, null);
|
expect(bottomSheetTheme.clipBehavior, null);
|
||||||
expect(bottomSheetTheme.constraints, null);
|
expect(bottomSheetTheme.constraints, null);
|
||||||
|
expect(bottomSheetTheme.dragHandleColor, null);
|
||||||
|
expect(bottomSheetTheme.dragHandleSize, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('Default BottomSheetThemeData debugFillProperties', (WidgetTester tester) async {
|
testWidgets('Default BottomSheetThemeData debugFillProperties', (WidgetTester tester) async {
|
||||||
@ -55,6 +57,8 @@ void main() {
|
|||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))),
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
constraints: BoxConstraints(minWidth: 200, maxWidth: 640),
|
constraints: BoxConstraints(minWidth: 200, maxWidth: 640),
|
||||||
|
dragHandleColor: Color(0xFFFFFFFF),
|
||||||
|
dragHandleSize: Size(20, 20)
|
||||||
).debugFillProperties(builder);
|
).debugFillProperties(builder);
|
||||||
|
|
||||||
final List<String> description = builder.properties
|
final List<String> description = builder.properties
|
||||||
@ -67,6 +71,8 @@ void main() {
|
|||||||
'elevation: 2.0',
|
'elevation: 2.0',
|
||||||
'shadowColor: Color(0xff00ffff)',
|
'shadowColor: Color(0xff00ffff)',
|
||||||
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(2.0))',
|
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(2.0))',
|
||||||
|
'dragHandleColor: Color(0xffffffff)',
|
||||||
|
'dragHandleSize: Size(20.0, 20.0)',
|
||||||
'clipBehavior: Clip.antiAlias',
|
'clipBehavior: Clip.antiAlias',
|
||||||
'constraints: BoxConstraints(200.0<=w<=640.0, 0.0<=h<=Infinity)',
|
'constraints: BoxConstraints(200.0<=w<=640.0, 0.0<=h<=Infinity)',
|
||||||
]);
|
]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user