Unverified Commit 17185191 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Fix drawers are draggable on desktop platforms (#100476)

parent bd683066
...@@ -565,6 +565,19 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro ...@@ -565,6 +565,19 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
final bool drawerIsStart = widget.alignment == DrawerAlignment.start; final bool drawerIsStart = widget.alignment == DrawerAlignment.start;
final EdgeInsets padding = MediaQuery.of(context).padding; final EdgeInsets padding = MediaQuery.of(context).padding;
final TextDirection textDirection = Directionality.of(context); final TextDirection textDirection = Directionality.of(context);
final bool isDesktop;
switch (Theme.of(context).platform) {
case TargetPlatform.android:
case TargetPlatform.iOS:
case TargetPlatform.fuchsia:
isDesktop = false;
break;
case TargetPlatform.macOS:
case TargetPlatform.linux:
case TargetPlatform.windows:
isDesktop = true;
break;
}
double? dragAreaWidth = widget.edgeDragWidth; double? dragAreaWidth = widget.edgeDragWidth;
if (widget.edgeDragWidth == null) { if (widget.edgeDragWidth == null) {
...@@ -581,7 +594,7 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro ...@@ -581,7 +594,7 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
} }
if (_controller.status == AnimationStatus.dismissed) { if (_controller.status == AnimationStatus.dismissed) {
if (widget.enableOpenDragGesture) { if (widget.enableOpenDragGesture && !isDesktop) {
return Align( return Align(
alignment: _drawerOuterAlignment, alignment: _drawerOuterAlignment,
child: GestureDetector( child: GestureDetector(
...@@ -612,52 +625,57 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro ...@@ -612,52 +625,57 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
break; break;
} }
assert(platformHasBackButton != null); assert(platformHasBackButton != null);
return GestureDetector(
key: _gestureDetectorKey, final Widget child = RepaintBoundary(
onHorizontalDragDown: _handleDragDown, child: Stack(
onHorizontalDragUpdate: _move, children: <Widget>[
onHorizontalDragEnd: _settle, BlockSemantics(
onHorizontalDragCancel: _handleDragCancel, child: ExcludeSemantics(
excludeFromSemantics: true, // On Android, the back button is used to dismiss a modal.
dragStartBehavior: widget.dragStartBehavior, excluding: platformHasBackButton,
child: RepaintBoundary( child: GestureDetector(
child: Stack( onTap: close,
children: <Widget>[ child: Semantics(
BlockSemantics( label: MaterialLocalizations.of(context).modalBarrierDismissLabel,
child: ExcludeSemantics( child: Container( // The drawer's "scrim"
// On Android, the back button is used to dismiss a modal. color: _scrimColorTween.evaluate(_controller),
excluding: platformHasBackButton,
child: GestureDetector(
onTap: close,
child: Semantics(
label: MaterialLocalizations.of(context).modalBarrierDismissLabel,
child: MouseRegion(
child: Container( // The drawer's "scrim"
color: _scrimColorTween.evaluate(_controller),
),
),
), ),
), ),
), ),
), ),
Align( ),
alignment: _drawerOuterAlignment, Align(
child: Align( alignment: _drawerOuterAlignment,
alignment: _drawerInnerAlignment, child: Align(
widthFactor: _controller.value, alignment: _drawerInnerAlignment,
child: RepaintBoundary( widthFactor: _controller.value,
child: FocusScope( child: RepaintBoundary(
key: _drawerKey, child: FocusScope(
node: _focusScopeNode, key: _drawerKey,
child: widget.child, node: _focusScopeNode,
), child: widget.child,
), ),
), ),
), ),
], ),
), ],
), ),
); );
if (isDesktop) {
return child;
}
return GestureDetector(
key: _gestureDetectorKey,
onHorizontalDragDown: _handleDragDown,
onHorizontalDragUpdate: _move,
onHorizontalDragEnd: _settle,
onHorizontalDragCancel: _handleDragCancel,
excludeFromSemantics: true,
dragStartBehavior: widget.dragStartBehavior,
child: child,
);
} }
} }
......
...@@ -1617,7 +1617,7 @@ class Scaffold extends StatefulWidget { ...@@ -1617,7 +1617,7 @@ class Scaffold extends StatefulWidget {
/// [Navigator.pop]. /// [Navigator.pop].
/// ///
/// {@tool dartpad} /// {@tool dartpad}
/// To disable the drawer edge swipe, set the /// To disable the drawer edge swipe on mobile, set the
/// [Scaffold.drawerEnableOpenDragGesture] to false. Then, use /// [Scaffold.drawerEnableOpenDragGesture] to false. Then, use
/// [ScaffoldState.openDrawer] to open the drawer and [Navigator.pop] to close /// [ScaffoldState.openDrawer] to open the drawer and [Navigator.pop] to close
/// it. /// it.
...@@ -1739,15 +1739,19 @@ class Scaffold extends StatefulWidget { ...@@ -1739,15 +1739,19 @@ class Scaffold extends StatefulWidget {
final double? drawerEdgeDragWidth; final double? drawerEdgeDragWidth;
/// Determines if the [Scaffold.drawer] can be opened with a drag /// Determines if the [Scaffold.drawer] can be opened with a drag
/// gesture. /// gesture on mobile.
///
/// On desktop platforms, the drawer is not draggable.
/// ///
/// By default, the drag gesture is enabled. /// By default, the drag gesture is enabled on mobile.
final bool drawerEnableOpenDragGesture; final bool drawerEnableOpenDragGesture;
/// Determines if the [Scaffold.endDrawer] can be opened with a /// Determines if the [Scaffold.endDrawer] can be opened with a
/// drag gesture. /// gesture on mobile.
///
/// On desktop platforms, the drawer is not draggable.
/// ///
/// By default, the drag gesture is enabled. /// By default, the drag gesture is enabled on mobile.
final bool endDrawerEnableOpenDragGesture; final bool endDrawerEnableOpenDragGesture;
/// Restoration ID to save and restore the state of the [Scaffold]. /// Restoration ID to save and restore the state of the [Scaffold].
......
...@@ -1777,7 +1777,7 @@ void main() { ...@@ -1777,7 +1777,7 @@ 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 { testWidgets('Drawer does not open with a drag gesture when it is disabled on mobile', (WidgetTester tester) async {
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Scaffold( home: Scaffold(
...@@ -1839,7 +1839,47 @@ void main() { ...@@ -1839,7 +1839,47 @@ void main() {
await tester.dragFrom(const Offset(300, 100), const Offset(-300, 0)); await tester.dragFrom(const Offset(300, 100), const Offset(-300, 0));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, false); expect(scaffoldState.isDrawerOpen, false);
}); }, variant: TargetPlatformVariant.mobile());
testWidgets('Drawer does not open with a drag gesture on dekstop', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
drawer: const Drawer(
child: Text('Drawer'),
),
body: const Text('Scaffold Body'),
appBar: AppBar(
centerTitle: true,
title: const Text('Title'),
),
),
),
);
final ScaffoldState scaffoldState = tester.state(find.byType(Scaffold));
expect(scaffoldState.isDrawerOpen, false);
// Test that we cannot open the drawer with a drag gesture.
await tester.dragFrom(const Offset(0, 100), const Offset(300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, false);
// Test that we can open the drawer with a tap gesture on drawer icon button.
final Finder drawerOpenButton = find.byType(IconButton).first;
await tester.tap(drawerOpenButton);
await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, true);
// Test that we cannot close the drawer with a drag gesture.
await tester.dragFrom(const Offset(300, 100), const Offset(-300, 0));
await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, true);
// Test that we can close the drawer with a tap gesture in the body.
await tester.tapAt(const Offset(500, 300));
await tester.pumpAndSettle();
expect(scaffoldState.isDrawerOpen, false);
}, variant: TargetPlatformVariant.desktop());
testWidgets('End drawer does not open with a drag gesture when it is disabled', (WidgetTester tester) async { testWidgets('End drawer does not open with a drag gesture when it is disabled', (WidgetTester tester) async {
late double screenWidth; late double screenWidth;
......
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