Add parameter to Scaffold so its possible to disable open Drawer drag gesture (#50925)
This commit is contained in:
parent
9295b34850
commit
74e564da2d
@ -232,6 +232,7 @@ class DrawerController extends StatefulWidget {
|
|||||||
this.dragStartBehavior = DragStartBehavior.start,
|
this.dragStartBehavior = DragStartBehavior.start,
|
||||||
this.scrimColor,
|
this.scrimColor,
|
||||||
this.edgeDragWidth,
|
this.edgeDragWidth,
|
||||||
|
this.enableOpenDragGesture = true,
|
||||||
}) : assert(child != null),
|
}) : assert(child != null),
|
||||||
assert(dragStartBehavior != null),
|
assert(dragStartBehavior != null),
|
||||||
assert(alignment != null),
|
assert(alignment != null),
|
||||||
@ -278,6 +279,11 @@ class DrawerController extends StatefulWidget {
|
|||||||
/// By default, the color used is [Colors.black54]
|
/// By default, the color used is [Colors.black54]
|
||||||
final Color scrimColor;
|
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
|
/// The width of the area within which a horizontal swipe will open the
|
||||||
/// drawer.
|
/// drawer.
|
||||||
///
|
///
|
||||||
@ -505,18 +511,22 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (_controller.status == AnimationStatus.dismissed) {
|
if (_controller.status == AnimationStatus.dismissed) {
|
||||||
return Align(
|
if (widget.enableOpenDragGesture) {
|
||||||
alignment: _drawerOuterAlignment,
|
return Align(
|
||||||
child: GestureDetector(
|
alignment: _drawerOuterAlignment,
|
||||||
key: _gestureDetectorKey,
|
child: GestureDetector(
|
||||||
onHorizontalDragUpdate: _move,
|
key: _gestureDetectorKey,
|
||||||
onHorizontalDragEnd: _settle,
|
onHorizontalDragUpdate: _move,
|
||||||
behavior: HitTestBehavior.translucent,
|
onHorizontalDragEnd: _settle,
|
||||||
excludeFromSemantics: true,
|
behavior: HitTestBehavior.translucent,
|
||||||
dragStartBehavior: widget.dragStartBehavior,
|
excludeFromSemantics: true,
|
||||||
child: Container(width: dragAreaWidth),
|
dragStartBehavior: widget.dragStartBehavior,
|
||||||
),
|
child: Container(width: dragAreaWidth),
|
||||||
);
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
bool platformHasBackButton;
|
bool platformHasBackButton;
|
||||||
switch (Theme.of(context).platform) {
|
switch (Theme.of(context).platform) {
|
||||||
|
@ -1011,6 +1011,8 @@ class Scaffold extends StatefulWidget {
|
|||||||
this.extendBodyBehindAppBar = false,
|
this.extendBodyBehindAppBar = false,
|
||||||
this.drawerScrimColor,
|
this.drawerScrimColor,
|
||||||
this.drawerEdgeDragWidth,
|
this.drawerEdgeDragWidth,
|
||||||
|
this.drawerEnableOpenDragGesture = true,
|
||||||
|
this.endDrawerEnableOpenDragGesture = true,
|
||||||
}) : assert(primary != null),
|
}) : assert(primary != null),
|
||||||
assert(extendBody != null),
|
assert(extendBody != null),
|
||||||
assert(extendBodyBehindAppBar != null),
|
assert(extendBodyBehindAppBar != null),
|
||||||
@ -1113,9 +1115,10 @@ class Scaffold extends StatefulWidget {
|
|||||||
/// To close the drawer, use [Navigator.pop].
|
/// To close the drawer, use [Navigator.pop].
|
||||||
///
|
///
|
||||||
/// {@tool dartpad --template=stateful_widget_material}
|
/// {@tool dartpad --template=stateful_widget_material}
|
||||||
/// To disable the drawer edge swipe, set the [Scaffold.drawerEdgeWidth] to 0.
|
/// To disable the drawer edge swipe, set the
|
||||||
/// Then, use [ScaffoldState.openDrawer] to open the drawer and
|
/// [Scaffold.drawerEnableOpenDragGesture] to false. Then, use
|
||||||
/// [Navigator.pop] to close it.
|
/// [ScaffoldState.openDrawer] to open the drawer and [Navigator.pop] to close
|
||||||
|
/// it.
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
/// 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].
|
/// To close the drawer, use [Navigator.pop].
|
||||||
///
|
///
|
||||||
/// {@tool dartpad --template=stateful_widget_material}
|
/// {@tool dartpad --template=stateful_widget_material}
|
||||||
/// To disable the drawer edge swipe, set the [Scaffold.drawerEdgeWidth]
|
/// To disable the drawer edge swipe, set the
|
||||||
/// to 0. Then, use [ScaffoldState.openEndDrawer] to open the drawer and
|
/// [Scaffold.endDrawerEnableOpenDragGesture] to false. Then, use
|
||||||
/// [Navigator.pop] to close it.
|
/// [ScaffoldState.openEndDrawer] to open the drawer and [Navigator.pop] to
|
||||||
|
/// close it.
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
/// 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`.
|
/// 20.0 will be added to `MediaQuery.of(context).padding.left`.
|
||||||
final double drawerEdgeDragWidth;
|
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
|
/// This flag is deprecated and fixes and issue with incorrect clipping
|
||||||
/// and positioning of the [SnackBar] set to [SnackBarBehavior.floating].
|
/// and positioning of the [SnackBar] set to [SnackBarBehavior.floating].
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
@ -2230,6 +2248,7 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
|
|||||||
dragStartBehavior: widget.drawerDragStartBehavior,
|
dragStartBehavior: widget.drawerDragStartBehavior,
|
||||||
scrimColor: widget.drawerScrimColor,
|
scrimColor: widget.drawerScrimColor,
|
||||||
edgeDragWidth: widget.drawerEdgeDragWidth,
|
edgeDragWidth: widget.drawerEdgeDragWidth,
|
||||||
|
enableOpenDragGesture: widget.endDrawerEnableOpenDragGesture,
|
||||||
),
|
),
|
||||||
_ScaffoldSlot.endDrawer,
|
_ScaffoldSlot.endDrawer,
|
||||||
// remove the side padding from the side we're not touching
|
// 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,
|
dragStartBehavior: widget.drawerDragStartBehavior,
|
||||||
scrimColor: widget.drawerScrimColor,
|
scrimColor: widget.drawerScrimColor,
|
||||||
edgeDragWidth: widget.drawerEdgeDragWidth,
|
edgeDragWidth: widget.drawerEdgeDragWidth,
|
||||||
|
enableOpenDragGesture: widget.drawerEnableOpenDragGesture,
|
||||||
),
|
),
|
||||||
_ScaffoldSlot.drawer,
|
_ScaffoldSlot.drawer,
|
||||||
// remove the side padding from the side we're not touching
|
// remove the side padding from the side we're not touching
|
||||||
|
@ -1596,6 +1596,142 @@ void main() {
|
|||||||
expect(scaffoldState.isDrawerOpen, true);
|
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 {
|
testWidgets('Nested scaffold body insets', (WidgetTester tester) async {
|
||||||
// Regression test for https://github.com/flutter/flutter/issues/20295
|
// Regression test for https://github.com/flutter/flutter/issues/20295
|
||||||
final Key bodyKey = UniqueKey();
|
final Key bodyKey = UniqueKey();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user