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
6ea0b2c9
Unverified
Commit
6ea0b2c9
authored
Nov 07, 2021
by
Darren Austin
Committed by
GitHub
Nov 07, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added `onDismiss` callback to ModalBarrier. (#83860)
parent
3fba55a1
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
88 additions
and
11 deletions
+88
-11
modal_barrier.dart
packages/flutter/lib/src/widgets/modal_barrier.dart
+27
-8
modal_barrier_test.dart
packages/flutter/test/widgets/modal_barrier_test.dart
+61
-3
No files found.
packages/flutter/lib/src/widgets/modal_barrier.dart
View file @
6ea0b2c9
...
@@ -34,6 +34,7 @@ class ModalBarrier extends StatelessWidget {
...
@@ -34,6 +34,7 @@ class ModalBarrier extends StatelessWidget {
Key
?
key
,
Key
?
key
,
this
.
color
,
this
.
color
,
this
.
dismissible
=
true
,
this
.
dismissible
=
true
,
this
.
onDismiss
,
this
.
semanticsLabel
,
this
.
semanticsLabel
,
this
.
barrierSemanticsDismissible
=
true
,
this
.
barrierSemanticsDismissible
=
true
,
})
:
super
(
key:
key
);
})
:
super
(
key:
key
);
...
@@ -46,7 +47,12 @@ class ModalBarrier extends StatelessWidget {
...
@@ -46,7 +47,12 @@ class ModalBarrier extends StatelessWidget {
/// [ModalBarrier] built by [ModalRoute] pages.
/// [ModalBarrier] built by [ModalRoute] pages.
final
Color
?
color
;
final
Color
?
color
;
/// Whether touching the barrier will pop the current route off the [Navigator].
/// Specifies if the barrier will be dismissed when the user taps on it.
///
/// If true, and [onDismiss] is non-null, [onDismiss] will be called,
/// otherwise the current route will be popped from the ambient [Navigator].
///
/// If false, tapping on the barrier will do nothing.
///
///
/// See also:
/// See also:
///
///
...
@@ -54,6 +60,16 @@ class ModalBarrier extends StatelessWidget {
...
@@ -54,6 +60,16 @@ class ModalBarrier extends StatelessWidget {
/// [ModalBarrier] built by [ModalRoute] pages.
/// [ModalBarrier] built by [ModalRoute] pages.
final
bool
dismissible
;
final
bool
dismissible
;
/// Called when the barrier is being dismissed.
///
/// If non-null [onDismiss] will be called in place of popping the current
/// route. It is up to the callback to handle dismissing the barrier.
///
/// If null, the ambient [Navigator]'s current route will be popped.
///
/// This field is ignored if [dismissible] is false.
final
VoidCallback
?
onDismiss
;
/// Whether the modal barrier semantics are included in the semantics tree.
/// Whether the modal barrier semantics are included in the semantics tree.
///
///
/// See also:
/// See also:
...
@@ -94,7 +110,15 @@ class ModalBarrier extends StatelessWidget {
...
@@ -94,7 +110,15 @@ class ModalBarrier extends StatelessWidget {
final
bool
modalBarrierSemanticsDismissible
=
barrierSemanticsDismissible
??
semanticsDismissible
;
final
bool
modalBarrierSemanticsDismissible
=
barrierSemanticsDismissible
??
semanticsDismissible
;
void
handleDismiss
()
{
void
handleDismiss
()
{
Navigator
.
maybePop
(
context
);
if
(
dismissible
)
{
if
(
onDismiss
!=
null
)
{
onDismiss
!();
}
else
{
Navigator
.
maybePop
(
context
);
}
}
else
{
SystemSound
.
play
(
SystemSoundType
.
alert
);
}
}
}
return
BlockSemantics
(
return
BlockSemantics
(
...
@@ -103,12 +127,7 @@ class ModalBarrier extends StatelessWidget {
...
@@ -103,12 +127,7 @@ class ModalBarrier extends StatelessWidget {
// modal barriers are not dismissible in accessibility mode.
// modal barriers are not dismissible in accessibility mode.
excluding:
!
semanticsDismissible
||
!
modalBarrierSemanticsDismissible
,
excluding:
!
semanticsDismissible
||
!
modalBarrierSemanticsDismissible
,
child:
_ModalBarrierGestureDetector
(
child:
_ModalBarrierGestureDetector
(
onDismiss:
()
{
onDismiss:
handleDismiss
,
if
(
dismissible
)
handleDismiss
();
else
SystemSound
.
play
(
SystemSoundType
.
alert
);
},
child:
Semantics
(
child:
Semantics
(
label:
semanticsDismissible
?
semanticsLabel
:
null
,
label:
semanticsDismissible
?
semanticsLabel
:
null
,
onDismiss:
semanticsDismissible
?
handleDismiss
:
null
,
onDismiss:
semanticsDismissible
?
handleDismiss
:
null
,
...
...
packages/flutter/test/widgets/modal_barrier_test.dart
View file @
6ea0b2c9
...
@@ -365,6 +365,60 @@ void main() {
...
@@ -365,6 +365,60 @@ void main() {
expect
(
willPopCalled
,
isTrue
);
expect
(
willPopCalled
,
isTrue
);
});
});
testWidgets
(
'ModalBarrier will call onDismiss callback'
,
(
WidgetTester
tester
)
async
{
bool
dismissCallbackCalled
=
false
;
final
Map
<
String
,
WidgetBuilder
>
routes
=
<
String
,
WidgetBuilder
>{
'/'
:
(
BuildContext
context
)
=>
const
FirstWidget
(),
'/modal'
:
(
BuildContext
context
)
=>
SecondWidget
(
onDismiss:
()
{
dismissCallbackCalled
=
true
;
}),
};
await
tester
.
pumpWidget
(
MaterialApp
(
routes:
routes
));
// Initially the barrier is not visible
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'barrier'
)),
findsNothing
);
// Tapping on X routes to the barrier
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pump
();
// begin transition
await
tester
.
pump
(
const
Duration
(
seconds:
1
));
// end transition
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'barrier'
)),
findsOneWidget
);
expect
(
dismissCallbackCalled
,
false
);
// Tap on the barrier
await
tester
.
tap
(
find
.
byKey
(
const
ValueKey
<
String
>(
'barrier'
)));
await
tester
.
pumpAndSettle
(
const
Duration
(
seconds:
1
));
// end transition
expect
(
dismissCallbackCalled
,
true
);
});
testWidgets
(
'ModalBarrier will not pop when given an onDismiss callback'
,
(
WidgetTester
tester
)
async
{
final
Map
<
String
,
WidgetBuilder
>
routes
=
<
String
,
WidgetBuilder
>{
'/'
:
(
BuildContext
context
)
=>
const
FirstWidget
(),
'/modal'
:
(
BuildContext
context
)
=>
SecondWidget
(
onDismiss:
()
{}),
};
await
tester
.
pumpWidget
(
MaterialApp
(
routes:
routes
));
// Initially the barrier is not visible
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'barrier'
)),
findsNothing
);
// Tapping on X routes to the barrier
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pump
();
// begin transition
await
tester
.
pump
(
const
Duration
(
seconds:
1
));
// end transition
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'barrier'
)),
findsOneWidget
);
// Tap on the barrier
await
tester
.
tap
(
find
.
byKey
(
const
ValueKey
<
String
>(
'barrier'
)));
await
tester
.
pumpAndSettle
(
const
Duration
(
seconds:
1
));
// end transition
expect
(
find
.
byKey
(
const
ValueKey
<
String
>(
'barrier'
)),
findsOneWidget
,
reason:
'The route should not have been dismissed by tapping the barrier, as there was a onDismiss callback given.'
,
);
});
testWidgets
(
'Undismissible ModalBarrier hidden in semantic tree'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'Undismissible ModalBarrier hidden in semantic tree'
,
(
WidgetTester
tester
)
async
{
final
SemanticsTester
semantics
=
SemanticsTester
(
tester
);
final
SemanticsTester
semantics
=
SemanticsTester
(
tester
);
await
tester
.
pumpWidget
(
const
ModalBarrier
(
dismissible:
false
));
await
tester
.
pumpWidget
(
const
ModalBarrier
(
dismissible:
false
));
...
@@ -442,11 +496,15 @@ class FirstWidget extends StatelessWidget {
...
@@ -442,11 +496,15 @@ class FirstWidget extends StatelessWidget {
}
}
class
SecondWidget
extends
StatelessWidget
{
class
SecondWidget
extends
StatelessWidget
{
const
SecondWidget
({
Key
?
key
})
:
super
(
key:
key
);
const
SecondWidget
({
Key
?
key
,
this
.
onDismiss
})
:
super
(
key:
key
);
final
VoidCallback
?
onDismiss
;
@override
@override
Widget
build
(
BuildContext
context
)
{
Widget
build
(
BuildContext
context
)
{
return
const
ModalBarrier
(
return
ModalBarrier
(
key:
ValueKey
<
String
>(
'barrier'
),
key:
const
ValueKey
<
String
>(
'barrier'
),
onDismiss:
onDismiss
,
);
);
}
}
}
}
...
...
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