Unverified Commit 9fc1fd15 authored by hangyu's avatar hangyu Committed by GitHub

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: 's avatarPierre-Louis <6655696+guidezpl@users.noreply.github.com>

* Update packages/flutter/lib/src/material/bottom_sheet.dart
Co-authored-by: 's avatarPierre-Louis <6655696+guidezpl@users.noreply.github.com>

* Update packages/flutter/lib/src/material/bottom_sheet.dart
Co-authored-by: 's avatarPierre-Louis <6655696+guidezpl@users.noreply.github.com>

* Update packages/flutter/lib/src/material/bottom_sheet.dart
Co-authored-by: 's avatarPierre-Louis <6655696+guidezpl@users.noreply.github.com>

* Update packages/flutter/lib/src/material/bottom_sheet.dart
Co-authored-by: 's avatarPierre-Louis <6655696+guidezpl@users.noreply.github.com>

* Update packages/flutter/lib/src/material/bottom_sheet.dart
Co-authored-by: 's avatarPierre-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: 's avatarPierre-Louis <6655696+guidezpl@users.noreply.github.com>
parent d58be8c7
......@@ -17,6 +17,7 @@ class _${blockName}DefaultsM3 extends BottomSheetThemeData {
elevation: ${elevation("md.comp.sheet.bottom.docked.standard.container")},
modalElevation: ${elevation("md.comp.sheet.bottom.docked.modal.container")},
shape: ${shape("md.comp.sheet.bottom.docked.container")},
constraints: const BoxConstraints(maxWidth: 640),
);
final BuildContext context;
......@@ -30,6 +31,12 @@ class _${blockName}DefaultsM3 extends BottomSheetThemeData {
@override
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")};
}
''';
}
......@@ -36,6 +36,9 @@ class BottomSheetThemeData with Diagnosticable {
this.shadowColor,
this.modalElevation,
this.shape,
this.showDragHandle,
this.dragHandleColor,
this.dragHandleSize,
this.clipBehavior,
this.constraints,
});
......@@ -80,6 +83,15 @@ class BottomSheetThemeData with Diagnosticable {
/// [BottomSheet] is rectangular.
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].
///
/// If null, [BottomSheet] uses [Clip.none].
......@@ -101,6 +113,9 @@ class BottomSheetThemeData with Diagnosticable {
Color? shadowColor,
double? modalElevation,
ShapeBorder? shape,
bool? showDragHandle,
Color? dragHandleColor,
Size? dragHandleSize,
Clip? clipBehavior,
BoxConstraints? constraints,
}) {
......@@ -113,6 +128,9 @@ class BottomSheetThemeData with Diagnosticable {
shadowColor: shadowColor ?? this.shadowColor,
modalElevation: modalElevation ?? this.modalElevation,
shape: shape ?? this.shape,
showDragHandle: showDragHandle ?? this.showDragHandle,
dragHandleColor: dragHandleColor ?? this.dragHandleColor,
dragHandleSize: dragHandleSize ?? this.dragHandleSize,
clipBehavior: clipBehavior ?? this.clipBehavior,
constraints: constraints ?? this.constraints,
);
......@@ -136,6 +154,9 @@ class BottomSheetThemeData with Diagnosticable {
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
modalElevation: lerpDouble(a?.modalElevation, b?.modalElevation, 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,
constraints: BoxConstraints.lerp(a?.constraints, b?.constraints, t),
);
......@@ -151,6 +172,9 @@ class BottomSheetThemeData with Diagnosticable {
shadowColor,
modalElevation,
shape,
showDragHandle,
dragHandleColor,
dragHandleSize,
clipBehavior,
constraints,
);
......@@ -172,6 +196,9 @@ class BottomSheetThemeData with Diagnosticable {
&& other.modalBarrierColor == modalBarrierColor
&& other.modalElevation == modalElevation
&& other.shape == shape
&& other.showDragHandle == showDragHandle
&& other.dragHandleColor == dragHandleColor
&& other.dragHandleSize == dragHandleSize
&& other.clipBehavior == clipBehavior
&& other.constraints == constraints;
}
......@@ -187,6 +214,9 @@ class BottomSheetThemeData with Diagnosticable {
properties.add(ColorProperty('modalBarrierColor', modalBarrierColor, defaultValue: null));
properties.add(DoubleProperty('modalElevation', modalElevation, 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<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
/// sheet.
/// * [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>(
WidgetBuilder builder, {
Color? backgroundColor,
......
......@@ -1008,6 +1008,138 @@ void main() {
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 {
await tester.pumpWidget(MaterialApp(
home: Scaffold(
......@@ -1617,6 +1749,21 @@ void main() {
});
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 {
await tester.pumpWidget(const MaterialApp(
......
......@@ -32,6 +32,8 @@ void main() {
expect(bottomSheetTheme.shape, null);
expect(bottomSheetTheme.clipBehavior, null);
expect(bottomSheetTheme.constraints, null);
expect(bottomSheetTheme.dragHandleColor, null);
expect(bottomSheetTheme.dragHandleSize, null);
});
testWidgets('Default BottomSheetThemeData debugFillProperties', (WidgetTester tester) async {
......@@ -55,6 +57,8 @@ void main() {
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))),
clipBehavior: Clip.antiAlias,
constraints: BoxConstraints(minWidth: 200, maxWidth: 640),
dragHandleColor: Color(0xFFFFFFFF),
dragHandleSize: Size(20, 20)
).debugFillProperties(builder);
final List<String> description = builder.properties
......@@ -67,6 +71,8 @@ void main() {
'elevation: 2.0',
'shadowColor: Color(0xff00ffff)',
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(2.0))',
'dragHandleColor: Color(0xffffffff)',
'dragHandleSize: Size(20.0, 20.0)',
'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