Add parameter to Scaffold so its possible to disable open Drawer drag gesture (#50925)

This commit is contained in:
Per Classon 2020-02-20 03:51:04 +01:00 committed by GitHub
parent 9295b34850
commit 74e564da2d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 186 additions and 20 deletions

View file

@ -232,6 +232,7 @@ class DrawerController extends StatefulWidget {
this.dragStartBehavior = DragStartBehavior.start,
this.scrimColor,
this.edgeDragWidth,
this.enableOpenDragGesture = true,
}) : assert(child != null),
assert(dragStartBehavior != null),
assert(alignment != null),
@ -278,6 +279,11 @@ class DrawerController extends StatefulWidget {
/// By default, the color used is [Colors.black54]
final Color scrimColor;
/// Determines if the [Drawer] can be opened with a drag gesture.
///
/// By default, the drag gesture is enabled.
final bool enableOpenDragGesture;
/// The width of the area within which a horizontal swipe will open the
/// drawer.
///
@ -505,18 +511,22 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
}
if (_controller.status == AnimationStatus.dismissed) {
return Align(
alignment: _drawerOuterAlignment,
child: GestureDetector(
key: _gestureDetectorKey,
onHorizontalDragUpdate: _move,
onHorizontalDragEnd: _settle,
behavior: HitTestBehavior.translucent,
excludeFromSemantics: true,
dragStartBehavior: widget.dragStartBehavior,
child: Container(width: dragAreaWidth),
),
);
if (widget.enableOpenDragGesture) {
return Align(
alignment: _drawerOuterAlignment,
child: GestureDetector(
key: _gestureDetectorKey,
onHorizontalDragUpdate: _move,
onHorizontalDragEnd: _settle,
behavior: HitTestBehavior.translucent,
excludeFromSemantics: true,
dragStartBehavior: widget.dragStartBehavior,
child: Container(width: dragAreaWidth),
),
);
} else {
return const SizedBox.shrink();
}
} else {
bool platformHasBackButton;
switch (Theme.of(context).platform) {

View file

@ -1011,6 +1011,8 @@ class Scaffold extends StatefulWidget {
this.extendBodyBehindAppBar = false,
this.drawerScrimColor,
this.drawerEdgeDragWidth,
this.drawerEnableOpenDragGesture = true,
this.endDrawerEnableOpenDragGesture = true,
}) : assert(primary != null),
assert(extendBody != null),
assert(extendBodyBehindAppBar != null),
@ -1113,9 +1115,10 @@ class Scaffold extends StatefulWidget {
/// To close the drawer, use [Navigator.pop].
///
/// {@tool dartpad --template=stateful_widget_material}
/// To disable the drawer edge swipe, set the [Scaffold.drawerEdgeWidth] to 0.
/// Then, use [ScaffoldState.openDrawer] to open the drawer and
/// [Navigator.pop] to close it.
/// To disable the drawer edge swipe, set the
/// [Scaffold.drawerEnableOpenDragGesture] to false. Then, use
/// [ScaffoldState.openDrawer] to open the drawer and [Navigator.pop] to close
/// it.
///
/// ```dart
/// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@ -1153,7 +1156,8 @@ class Scaffold extends StatefulWidget {
/// ),
/// ),
/// ),
/// drawerEdgeDragWidth: 0.0, // Disable opening the drawer with a swipe gesture.
/// // Disable opening the drawer with a swipe gesture.
/// drawerEnableOpenDragGesture: false,
/// );
/// }
/// ```
@ -1171,9 +1175,10 @@ class Scaffold extends StatefulWidget {
/// To close the drawer, use [Navigator.pop].
///
/// {@tool dartpad --template=stateful_widget_material}
/// To disable the drawer edge swipe, set the [Scaffold.drawerEdgeWidth]
/// to 0. Then, use [ScaffoldState.openEndDrawer] to open the drawer and
/// [Navigator.pop] to close it.
/// To disable the drawer edge swipe, set the
/// [Scaffold.endDrawerEnableOpenDragGesture] to false. Then, use
/// [ScaffoldState.openEndDrawer] to open the drawer and [Navigator.pop] to
/// close it.
///
/// ```dart
/// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
@ -1211,7 +1216,8 @@ class Scaffold extends StatefulWidget {
/// ),
/// ),
/// ),
/// drawerEdgeDragWidth: 0.0, // Disable opening the drawer with a swipe gesture.
/// // Disable opening the end drawer with a swipe gesture.
/// endDrawerEnableOpenDragGesture: false,
/// );
/// }
/// ```
@ -1313,6 +1319,18 @@ class Scaffold extends StatefulWidget {
/// 20.0 will be added to `MediaQuery.of(context).padding.left`.
final double drawerEdgeDragWidth;
/// Determines if the [Scaffold.drawer] can be opened with a drag
/// gesture.
///
/// By default, the drag gesture is enabled.
final bool drawerEnableOpenDragGesture;
/// Determines if the [Scaffold.endDrawer] can be opened with a
/// drag gesture.
///
/// By default, the drag gesture is enabled.
final bool endDrawerEnableOpenDragGesture;
/// This flag is deprecated and fixes and issue with incorrect clipping
/// and positioning of the [SnackBar] set to [SnackBarBehavior.floating].
@Deprecated(
@ -2230,6 +2248,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
dragStartBehavior: widget.drawerDragStartBehavior,
scrimColor: widget.drawerScrimColor,
edgeDragWidth: widget.drawerEdgeDragWidth,
enableOpenDragGesture: widget.endDrawerEnableOpenDragGesture,
),
_ScaffoldSlot.endDrawer,
// remove the side padding from the side we're not touching
@ -2254,6 +2273,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
dragStartBehavior: widget.drawerDragStartBehavior,
scrimColor: widget.drawerScrimColor,
edgeDragWidth: widget.drawerEdgeDragWidth,
enableOpenDragGesture: widget.drawerEnableOpenDragGesture,
),
_ScaffoldSlot.drawer,
// remove the side padding from the side we're not touching

View file

@ -1596,6 +1596,142 @@ void main() {
expect(scaffoldState.isDrawerOpen, true);
});
testWidgets('Drawer does not open with a drag gesture when it is disabled', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
drawer: const Drawer(
child: Text('Drawer'),
),
drawerEnableOpenDragGesture: true,
body: const Text('Scaffold Body'),
appBar: AppBar(
centerTitle: true,
title: const Text('Title'),
),
),
),
);
ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));
expect(scaffoldState.isDrawerOpen, false);
// Test that we can open the drawer with a drag gesture when
// `Scaffold.drawerEnableDragGesture` is true.
await tester.dragFrom(const Offset(0, 100), const Offset(300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, true);
await tester.dragFrom(const Offset(300, 100), const Offset(-300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, false);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
drawer: const Drawer(
child: Text('Drawer'),
),
drawerEnableOpenDragGesture: false,
body: const Text('Scaffold body'),
appBar: AppBar(
centerTitle: true,
title: const Text('Title'),
),
),
),
);
scaffoldState = tester.state(find.byType(Scaffold));
expect(scaffoldState.isDrawerOpen, false);
// Test that we cannot open the drawer with a drag gesture when
// `Scaffold.drawerEnableDragGesture` is false.
await tester.dragFrom(const Offset(0, 100), const Offset(300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, false);
// Test that we can close drawer with a drag gesture when
// `Scaffold.drawerEnableDragGesture` is false.
final Finder drawerOpenButton = find.byType(IconButton).first;
await tester.tap(drawerOpenButton);
await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, true);
await tester.dragFrom(const Offset(300, 100), const Offset(-300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, false);
});
testWidgets('End drawer does not open with a drag gesture when it is disabled', (WidgetTester tester) async {
double screenWidth;
await tester.pumpWidget(
MaterialApp(
home: Builder(
builder: (BuildContext context) {
screenWidth = MediaQuery.of(context).size.width;
return Scaffold(
endDrawer: const Drawer(
child: Text('Drawer'),
),
endDrawerEnableOpenDragGesture: true,
body: const Text('Scaffold Body'),
appBar: AppBar(
centerTitle: true,
title: const Text('Title'),
),
);
}
),
),
);
ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));
expect(scaffoldState.isEndDrawerOpen, false);
// Test that we can open the end drawer with a drag gesture when
// `Scaffold.endDrawerEnableDragGesture` is true.
await tester.dragFrom(Offset(screenWidth - 1, 100), const Offset(-300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isEndDrawerOpen, true);
await tester.dragFrom(Offset(screenWidth - 300, 100), const Offset(300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isEndDrawerOpen, false);
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
endDrawer: const Drawer(
child: Text('Drawer'),
),
endDrawerEnableOpenDragGesture: false,
body: const Text('Scaffold body'),
appBar: AppBar(
centerTitle: true,
title: const Text('Title'),
),
),
),
);
scaffoldState = tester.state(find.byType(Scaffold));
expect(scaffoldState.isEndDrawerOpen, false);
// Test that we cannot open the end drawer with a drag gesture when
// `Scaffold.endDrawerEnableDragGesture` is false.
await tester.dragFrom(Offset(screenWidth - 1, 100), const Offset(-300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isEndDrawerOpen, false);
// Test that we can close the end drawer a with drag gesture when
// `Scaffold.endDrawerEnableDragGesture` is false.
final Finder endDrawerOpenButton = find.byType(IconButton).first;
await tester.tap(endDrawerOpenButton);
await tester.pumpAndSettle();
expect(scaffoldState.isEndDrawerOpen, true);
await tester.dragFrom(Offset(screenWidth - 300, 100), const Offset(300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isEndDrawerOpen, false);
});
testWidgets('Nested scaffold body insets', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/20295
final Key bodyKey = UniqueKey();