Skip to content

Commit 38805a4

Browse files
authored
Fix clipBehavior for Drawer with shape and add clipBehavior property. (#124104)
1 parent 9e4b5fb commit 38805a4

File tree

2 files changed

+117
-3
lines changed

2 files changed

+117
-3
lines changed

packages/flutter/lib/src/material/drawer.dart

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@ class Drawer extends StatelessWidget {
153153
this.width,
154154
this.child,
155155
this.semanticLabel,
156+
this.clipBehavior,
156157
}) : assert(elevation == null || elevation >= 0.0);
157158

158159
/// Sets the color of the [Material] that holds all of the [Drawer]'s
@@ -237,6 +238,14 @@ class Drawer extends StatelessWidget {
237238
/// value is used.
238239
final String? semanticLabel;
239240

241+
/// {@macro flutter.material.Material.clipBehavior}
242+
///
243+
/// The [clipBehavior] argument specifies how to clip the drawer's [shape].
244+
///
245+
/// If the drawer has a [shape], it defaults to [Clip.hardEdge]. Otherwise,
246+
/// defaults to [Clip.none].
247+
final Clip? clipBehavior;
248+
240249
@override
241250
Widget build(BuildContext context) {
242251
assert(debugCheckHasMaterialLocalizations(context));
@@ -255,6 +264,9 @@ class Drawer extends StatelessWidget {
255264
final bool useMaterial3 = Theme.of(context).useMaterial3;
256265
final bool isDrawerStart = DrawerController.maybeOf(context)?.alignment != DrawerAlignment.end;
257266
final DrawerThemeData defaults= useMaterial3 ? _DrawerDefaultsM3(context): _DrawerDefaultsM2(context);
267+
final ShapeBorder? effectiveShape = shape ?? (isDrawerStart
268+
? (drawerTheme.shape ?? defaults.shape)
269+
: (drawerTheme.endShape ?? defaults.endShape));
258270
return Semantics(
259271
scopesRoute: true,
260272
namesRoute: true,
@@ -267,9 +279,8 @@ class Drawer extends StatelessWidget {
267279
elevation: elevation ?? drawerTheme.elevation ?? defaults.elevation!,
268280
shadowColor: shadowColor ?? drawerTheme.shadowColor ?? defaults.shadowColor,
269281
surfaceTintColor: surfaceTintColor ?? drawerTheme.surfaceTintColor ?? defaults.surfaceTintColor,
270-
shape: shape ?? (isDrawerStart
271-
? (drawerTheme.shape ?? defaults.shape)
272-
: (drawerTheme.endShape ?? defaults.endShape)),
282+
shape: effectiveShape,
283+
clipBehavior: effectiveShape != null ? (clipBehavior ?? Clip.hardEdge) : Clip.none,
273284
child: child,
274285
),
275286
),

packages/flutter/test/material/drawer_test.dart

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,57 @@ void main() {
688688
);
689689
});
690690

691+
testWidgets('Drawer clip behavior', (WidgetTester tester) async {
692+
await tester.pumpWidget(
693+
MaterialApp(
694+
theme: ThemeData(useMaterial3: true),
695+
home: const Scaffold(
696+
drawer: Drawer(),
697+
),
698+
),
699+
);
700+
701+
final Finder drawerMaterial = find.descendant(
702+
of: find.byType(Drawer),
703+
matching: find.byType(Material),
704+
);
705+
706+
final ScaffoldState state = tester.firstState(find.byType(Scaffold));
707+
708+
// Open the drawer.
709+
state.openDrawer();
710+
await tester.pump();
711+
await tester.pump(const Duration(seconds: 1));
712+
713+
// Test default clip behavior.
714+
Material material = tester.widget<Material>(drawerMaterial);
715+
expect(material.clipBehavior, Clip.hardEdge);
716+
717+
state.closeDrawer();
718+
await tester.pumpAndSettle();
719+
720+
// Provide a custom clip behavior.
721+
await tester.pumpWidget(
722+
MaterialApp(
723+
theme: ThemeData(useMaterial3: true),
724+
home: const Scaffold(
725+
drawer: Drawer(
726+
clipBehavior: Clip.antiAlias,
727+
),
728+
),
729+
),
730+
);
731+
732+
// Open the drawer again.
733+
state.openDrawer();
734+
await tester.pump();
735+
await tester.pump(const Duration(seconds: 1));
736+
737+
// Clip behavior is now updated.
738+
material = tester.widget<Material>(drawerMaterial);
739+
expect(material.clipBehavior, Clip.antiAlias);
740+
});
741+
691742
group('Material 2', () {
692743
// Tests that are only relevant for Material 2. Once ThemeData.useMaterial3
693744
// is turned on by default, these tests can be removed.
@@ -732,5 +783,57 @@ void main() {
732783
material = tester.widget<Material>(drawerMaterial);
733784
expect(material.shape, null);
734785
});
786+
787+
testWidgets('Drawer clip behavior', (WidgetTester tester) async {
788+
await tester.pumpWidget(
789+
MaterialApp(
790+
theme: ThemeData(useMaterial3: false),
791+
home: const Scaffold(
792+
drawer: Drawer(),
793+
),
794+
),
795+
);
796+
797+
final Finder drawerMaterial = find.descendant(
798+
of: find.byType(Drawer),
799+
matching: find.byType(Material),
800+
);
801+
802+
final ScaffoldState state = tester.firstState(find.byType(Scaffold));
803+
804+
// Open the drawer.
805+
state.openDrawer();
806+
await tester.pump();
807+
await tester.pump(const Duration(seconds: 1));
808+
809+
// Test default clip behavior.
810+
Material material = tester.widget<Material>(drawerMaterial);
811+
expect(material.clipBehavior, Clip.none);
812+
813+
state.closeDrawer();
814+
await tester.pumpAndSettle();
815+
816+
// Provide a shape and custom clip behavior.
817+
await tester.pumpWidget(
818+
MaterialApp(
819+
theme: ThemeData(useMaterial3: false),
820+
home: const Scaffold(
821+
drawer: Drawer(
822+
clipBehavior: Clip.hardEdge,
823+
shape: RoundedRectangleBorder(),
824+
),
825+
),
826+
),
827+
);
828+
829+
// Open the drawer again.
830+
state.openDrawer();
831+
await tester.pump();
832+
await tester.pump(const Duration(seconds: 1));
833+
834+
// Clip behavior is now updated.
835+
material = tester.widget<Material>(drawerMaterial);
836+
expect(material.clipBehavior, Clip.hardEdge);
837+
});
735838
});
736839
}

0 commit comments

Comments
 (0)