mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Fix drawers are draggable on desktop platforms (#100476)
This commit is contained in:
parent
bd683066cb
commit
1718519188
@ -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
|
|||||||
}
|
}
|
||||||
|
|
||||||
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,15 +625,8 @@ 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,
|
|
||||||
onHorizontalDragUpdate: _move,
|
|
||||||
onHorizontalDragEnd: _settle,
|
|
||||||
onHorizontalDragCancel: _handleDragCancel,
|
|
||||||
excludeFromSemantics: true,
|
|
||||||
dragStartBehavior: widget.dragStartBehavior,
|
|
||||||
child: RepaintBoundary(
|
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
BlockSemantics(
|
BlockSemantics(
|
||||||
@ -631,7 +637,6 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
|
|||||||
onTap: close,
|
onTap: close,
|
||||||
child: Semantics(
|
child: Semantics(
|
||||||
label: MaterialLocalizations.of(context).modalBarrierDismissLabel,
|
label: MaterialLocalizations.of(context).modalBarrierDismissLabel,
|
||||||
child: MouseRegion(
|
|
||||||
child: Container( // The drawer's "scrim"
|
child: Container( // The drawer's "scrim"
|
||||||
color: _scrimColorTween.evaluate(_controller),
|
color: _scrimColorTween.evaluate(_controller),
|
||||||
),
|
),
|
||||||
@ -639,7 +644,6 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
Align(
|
Align(
|
||||||
alignment: _drawerOuterAlignment,
|
alignment: _drawerOuterAlignment,
|
||||||
child: Align(
|
child: Align(
|
||||||
@ -656,7 +660,21 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
|
|
||||||
|
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 {
|
|||||||
/// [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 {
|
|||||||
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.
|
||||||
///
|
///
|
||||||
/// By default, the drag gesture is enabled.
|
/// On desktop platforms, the drawer is not draggable.
|
||||||
|
///
|
||||||
|
/// 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.
|
||||||
///
|
///
|
||||||
/// By default, the drag gesture is enabled.
|
/// On desktop platforms, the drawer is not draggable.
|
||||||
|
///
|
||||||
|
/// 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() {
|
|||||||
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() {
|
|||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user