Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
8fe82bbe
Unverified
Commit
8fe82bbe
authored
Jun 29, 2022
by
Taha Tesser
Committed by
GitHub
Jun 29, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Scaffold drawers escape dismiss action. (#106186)
parent
1d5c189d
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
112 additions
and
36 deletions
+112
-36
drawer.dart
packages/flutter/lib/src/material/drawer.dart
+3
-2
scaffold.dart
packages/flutter/lib/src/material/scaffold.dart
+42
-20
debug_test.dart
packages/flutter/test/material/debug_test.dart
+2
-0
scaffold_test.dart
packages/flutter/test/material/scaffold_test.dart
+65
-14
No files found.
packages/flutter/lib/src/material/drawer.dart
View file @
8fe82bbe
...
...
@@ -111,8 +111,9 @@ const Duration _kBaseSettleDuration = Duration(milliseconds: 246);
/// ```
/// {@end-tool}
///
/// An open drawer can be closed by calling [Navigator.pop]. For example
/// a drawer item might close the drawer when tapped:
/// An open drawer may be closed with a swipe to close gesture, pressing the
/// the escape key, by tapping the scrim, or by calling pop route function such as
/// [Navigator.pop]. For example a drawer item might close the drawer when tapped:
///
/// ```dart
/// ListTile(
...
...
packages/flutter/lib/src/material/scaffold.dart
View file @
8fe82bbe
...
...
@@ -1614,8 +1614,8 @@ class Scaffold extends StatefulWidget {
///
/// To open the drawer, use the [ScaffoldState.openDrawer] function.
///
/// To close the drawer, use either [ScaffoldState.closeDrawer]
or
///
[Navigator.pop]
.
/// To close the drawer, use either [ScaffoldState.closeDrawer]
, [Navigator.pop]
///
or press the escape key on the keyboard
.
///
/// {@tool dartpad}
/// To disable the drawer edge swipe on mobile, set the
...
...
@@ -1638,8 +1638,8 @@ class Scaffold extends StatefulWidget {
///
/// To open the drawer, use the [ScaffoldState.openEndDrawer] function.
///
/// To close the drawer, use either [ScaffoldState.closeEndDrawer]
or
///
[Navigator.pop]
.
/// To close the drawer, use either [ScaffoldState.closeEndDrawer]
, [Navigator.pop]
///
or press the escape key on the keyboard
.
///
/// {@tool dartpad}
/// To disable the drawer edge swipe, set the
...
...
@@ -2875,23 +2875,28 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
child:
Material
(
color:
widget
.
backgroundColor
??
themeData
.
scaffoldBackgroundColor
,
child:
AnimatedBuilder
(
animation:
_floatingActionButtonMoveController
,
builder:
(
BuildContext
context
,
Widget
?
child
)
{
return
CustomMultiChildLayout
(
delegate:
_ScaffoldLayout
(
extendBody:
extendBody
,
extendBodyBehindAppBar:
widget
.
extendBodyBehindAppBar
,
minInsets:
minInsets
,
minViewPadding:
minViewPadding
,
currentFloatingActionButtonLocation:
_floatingActionButtonLocation
!,
floatingActionButtonMoveAnimationProgress:
_floatingActionButtonMoveController
.
value
,
floatingActionButtonMotionAnimator:
_floatingActionButtonAnimator
,
geometryNotifier:
_geometryNotifier
,
previousFloatingActionButtonLocation:
_previousFloatingActionButtonLocation
!,
textDirection:
textDirection
,
isSnackBarFloating:
isSnackBarFloating
,
extendBodyBehindMaterialBanner:
extendBodyBehindMaterialBanner
,
snackBarWidth:
snackBarWidth
,
return
Actions
(
actions:
<
Type
,
Action
<
Intent
>>{
DismissIntent:
_DismissDrawerAction
(
context
),
},
child:
CustomMultiChildLayout
(
delegate:
_ScaffoldLayout
(
extendBody:
extendBody
,
extendBodyBehindAppBar:
widget
.
extendBodyBehindAppBar
,
minInsets:
minInsets
,
minViewPadding:
minViewPadding
,
currentFloatingActionButtonLocation:
_floatingActionButtonLocation
!,
floatingActionButtonMoveAnimationProgress:
_floatingActionButtonMoveController
.
value
,
floatingActionButtonMotionAnimator:
_floatingActionButtonAnimator
,
geometryNotifier:
_geometryNotifier
,
previousFloatingActionButtonLocation:
_previousFloatingActionButtonLocation
!,
textDirection:
textDirection
,
isSnackBarFloating:
isSnackBarFloating
,
extendBodyBehindMaterialBanner:
extendBodyBehindMaterialBanner
,
snackBarWidth:
snackBarWidth
,
),
children:
children
,
),
children:
children
,
);
}),
),
...
...
@@ -2900,6 +2905,23 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin, Resto
}
}
class
_DismissDrawerAction
extends
DismissAction
{
_DismissDrawerAction
(
this
.
context
);
final
BuildContext
context
;
@override
bool
isEnabled
(
DismissIntent
intent
)
{
return
Scaffold
.
of
(
context
).
isDrawerOpen
||
Scaffold
.
of
(
context
).
isEndDrawerOpen
;
}
@override
void
invoke
(
DismissIntent
intent
)
{
Scaffold
.
of
(
context
).
closeDrawer
();
Scaffold
.
of
(
context
).
closeEndDrawer
();
}
}
/// An interface for controlling a feature of a [Scaffold].
///
/// Commonly obtained from [ScaffoldMessengerState.showSnackBar] or
...
...
packages/flutter/test/material/debug_test.dart
View file @
8fe82bbe
...
...
@@ -350,6 +350,8 @@ void main() {
' MediaQuery
\n
'
' LayoutId-[<_ScaffoldSlot.snackBar>]
\n
'
' CustomMultiChildLayout
\n
'
' _ActionsMarker
\n
'
' Actions
\n
'
' AnimatedBuilder
\n
'
' DefaultTextStyle
\n
'
' AnimatedDefaultTextStyle
\n
'
...
...
packages/flutter/test/material/scaffold_test.dart
View file @
8fe82bbe
...
...
@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
import
'package:flutter/gestures.dart'
show
DragStartBehavior
;
import
'package:flutter/material.dart'
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
import
'package:flutter_test/flutter_test.dart'
;
import
'../widgets/semantics_tester.dart'
;
...
...
@@ -37,17 +38,17 @@ void main() {
scaffoldState
.
openDrawer
();
await
tester
.
pumpAndSettle
();
expect
(
true
,
isDrawerOpen
);
expect
(
isDrawerOpen
,
true
);
scaffoldState
.
openEndDrawer
();
await
tester
.
pumpAndSettle
();
expect
(
false
,
isDrawerOpen
);
expect
(
isDrawerOpen
,
false
);
scaffoldState
.
openEndDrawer
();
await
tester
.
pumpAndSettle
();
expect
(
true
,
isEndDrawerOpen
);
expect
(
isEndDrawerOpen
,
true
);
scaffoldState
.
openDrawer
();
await
tester
.
pumpAndSettle
();
expect
(
false
,
isEndDrawerOpen
);
expect
(
isEndDrawerOpen
,
false
);
});
testWidgets
(
'Scaffold drawer callback test - only call when changed'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -74,14 +75,14 @@ void main() {
));
await
tester
.
flingFrom
(
Offset
.
zero
,
const
Offset
(
10.0
,
0.0
),
10.0
);
expect
(
false
,
onDrawerChangedCalled
);
expect
(
onDrawerChangedCalled
,
false
);
await
tester
.
pumpAndSettle
();
final
double
width
=
tester
.
getSize
(
find
.
byType
(
MaterialApp
)).
width
;
await
tester
.
flingFrom
(
Offset
(
width
-
1
,
0.0
),
const
Offset
(-
10.0
,
0.0
),
10.0
);
await
tester
.
pumpAndSettle
();
expect
(
false
,
onEndDrawerChangedCalled
);
expect
(
onEndDrawerChangedCalled
,
false
);
});
testWidgets
(
'Scaffold control test'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -1572,29 +1573,29 @@ void main() {
await
tester
.
tap
(
drawerOpenButton
);
await
tester
.
pumpAndSettle
();
expect
(
true
,
scaffoldState
.
isDrawerOpen
);
expect
(
scaffoldState
.
isDrawerOpen
,
true
);
await
tester
.
tap
(
endDrawerOpenButton
,
warnIfMissed:
false
);
// hits the modal barrier
await
tester
.
pumpAndSettle
();
expect
(
false
,
scaffoldState
.
isDrawerOpen
);
expect
(
scaffoldState
.
isDrawerOpen
,
false
);
await
tester
.
tap
(
endDrawerOpenButton
);
await
tester
.
pumpAndSettle
();
expect
(
true
,
scaffoldState
.
isEndDrawerOpen
);
expect
(
scaffoldState
.
isEndDrawerOpen
,
true
);
await
tester
.
tap
(
drawerOpenButton
,
warnIfMissed:
false
);
// hits the modal barrier
await
tester
.
pumpAndSettle
();
expect
(
false
,
scaffoldState
.
isEndDrawerOpen
);
expect
(
scaffoldState
.
isEndDrawerOpen
,
false
);
scaffoldState
.
openDrawer
();
expect
(
true
,
scaffoldState
.
isDrawerOpen
);
expect
(
scaffoldState
.
isDrawerOpen
,
true
);
await
tester
.
tap
(
endDrawerOpenButton
,
warnIfMissed:
false
);
// hits the modal barrier
await
tester
.
pumpAndSettle
();
expect
(
false
,
scaffoldState
.
isDrawerOpen
);
expect
(
scaffoldState
.
isDrawerOpen
,
false
);
scaffoldState
.
openEndDrawer
();
expect
(
true
,
scaffoldState
.
isEndDrawerOpen
);
expect
(
scaffoldState
.
isEndDrawerOpen
,
true
);
scaffoldState
.
openDrawer
();
expect
(
true
,
scaffoldState
.
isDrawerOpen
);
expect
(
scaffoldState
.
isDrawerOpen
,
true
);
});
testWidgets
(
'Dual Drawer Opening'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -2405,6 +2406,8 @@ void main() {
' MediaQuery
\n
'
' LayoutId-[<_ScaffoldSlot.body>]
\n
'
' CustomMultiChildLayout
\n
'
' _ActionsMarker
\n
'
' Actions
\n
'
' AnimatedBuilder
\n
'
' DefaultTextStyle
\n
'
' AnimatedDefaultTextStyle
\n
'
...
...
@@ -2497,6 +2500,54 @@ void main() {
await
tester
.
pumpAndSettle
();
expect
(
find
.
text
(
snackBarContent
),
findsNothing
);
});
testWidgets
(
'Drawer can be dismissed with escape keyboard shortcut'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/106131
bool
isDrawerOpen
=
false
;
bool
isEndDrawerOpen
=
false
;
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Scaffold
(
drawer:
Container
(
color:
Colors
.
blue
,
),
onDrawerChanged:
(
bool
isOpen
)
{
isDrawerOpen
=
isOpen
;
},
endDrawer:
Container
(
color:
Colors
.
green
,
),
onEndDrawerChanged:
(
bool
isOpen
)
{
isEndDrawerOpen
=
isOpen
;
},
body:
Container
(),
),
));
final
ScaffoldState
scaffoldState
=
tester
.
state
(
find
.
byType
(
Scaffold
));
scaffoldState
.
openDrawer
();
await
tester
.
pumpAndSettle
();
expect
(
isDrawerOpen
,
true
);
expect
(
isEndDrawerOpen
,
false
);
// Try to dismiss the drawer with the shortcut key
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
escape
);
await
tester
.
pumpAndSettle
();
expect
(
isDrawerOpen
,
false
);
expect
(
isEndDrawerOpen
,
false
);
scaffoldState
.
openEndDrawer
();
await
tester
.
pumpAndSettle
();
expect
(
isDrawerOpen
,
false
);
expect
(
isEndDrawerOpen
,
true
);
// Try to dismiss the drawer with the shortcut key
await
tester
.
sendKeyEvent
(
LogicalKeyboardKey
.
escape
);
await
tester
.
pumpAndSettle
();
expect
(
isDrawerOpen
,
false
);
expect
(
isEndDrawerOpen
,
false
);
});
}
class
_GeometryListener
extends
StatefulWidget
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment