Dismiss Modal Barrier on handleTapCancel
(#98191)
This commit is contained in:
parent
0acfb216ac
commit
58ad6e1bef
@ -47,7 +47,8 @@ class ModalBarrier extends StatelessWidget {
|
|||||||
/// [ModalBarrier] built by [ModalRoute] pages.
|
/// [ModalBarrier] built by [ModalRoute] pages.
|
||||||
final Color? color;
|
final Color? color;
|
||||||
|
|
||||||
/// Specifies if the barrier will be dismissed when the user taps on it.
|
/// Specifies if the barrier will be dismissed when the user taps or
|
||||||
|
/// performs a scroll gesture on it.
|
||||||
///
|
///
|
||||||
/// If true, and [onDismiss] is non-null, [onDismiss] will be called,
|
/// If true, and [onDismiss] is non-null, [onDismiss] will be called,
|
||||||
/// otherwise the current route will be popped from the ambient [Navigator].
|
/// otherwise the current route will be popped from the ambient [Navigator].
|
||||||
@ -228,12 +229,14 @@ class _AnyTapGestureRecognizer extends BaseTapGestureRecognizer {
|
|||||||
: super(debugOwner: debugOwner);
|
: super(debugOwner: debugOwner);
|
||||||
|
|
||||||
VoidCallback? onAnyTapUp;
|
VoidCallback? onAnyTapUp;
|
||||||
|
VoidCallback? onAnyTapCancel;
|
||||||
|
|
||||||
@protected
|
@protected
|
||||||
@override
|
@override
|
||||||
bool isPointerAllowed(PointerDownEvent event) {
|
bool isPointerAllowed(PointerDownEvent event) {
|
||||||
if (onAnyTapUp == null)
|
if (onAnyTapUp == null && onAnyTapCancel == null) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
return super.isPointerAllowed(event);
|
return super.isPointerAllowed(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +255,7 @@ class _AnyTapGestureRecognizer extends BaseTapGestureRecognizer {
|
|||||||
@protected
|
@protected
|
||||||
@override
|
@override
|
||||||
void handleTapCancel({PointerDownEvent? down, PointerCancelEvent? cancel, String? reason}) {
|
void handleTapCancel({PointerDownEvent? down, PointerCancelEvent? cancel, String? reason}) {
|
||||||
// Do nothing.
|
onAnyTapCancel?.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -272,9 +275,10 @@ class _ModalBarrierSemanticsDelegate extends SemanticsGestureDelegate {
|
|||||||
|
|
||||||
|
|
||||||
class _AnyTapGestureRecognizerFactory extends GestureRecognizerFactory<_AnyTapGestureRecognizer> {
|
class _AnyTapGestureRecognizerFactory extends GestureRecognizerFactory<_AnyTapGestureRecognizer> {
|
||||||
const _AnyTapGestureRecognizerFactory({this.onAnyTapUp});
|
const _AnyTapGestureRecognizerFactory({this.onAnyTapUp, this.onAnyTapCancel});
|
||||||
|
|
||||||
final VoidCallback? onAnyTapUp;
|
final VoidCallback? onAnyTapUp;
|
||||||
|
final VoidCallback? onAnyTapCancel;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_AnyTapGestureRecognizer constructor() => _AnyTapGestureRecognizer();
|
_AnyTapGestureRecognizer constructor() => _AnyTapGestureRecognizer();
|
||||||
@ -282,6 +286,7 @@ class _AnyTapGestureRecognizerFactory extends GestureRecognizerFactory<_AnyTapGe
|
|||||||
@override
|
@override
|
||||||
void initializer(_AnyTapGestureRecognizer instance) {
|
void initializer(_AnyTapGestureRecognizer instance) {
|
||||||
instance.onAnyTapUp = onAnyTapUp;
|
instance.onAnyTapUp = onAnyTapUp;
|
||||||
|
instance.onAnyTapCancel = onAnyTapCancel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +312,7 @@ class _ModalBarrierGestureDetector extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{
|
final Map<Type, GestureRecognizerFactory> gestures = <Type, GestureRecognizerFactory>{
|
||||||
_AnyTapGestureRecognizer: _AnyTapGestureRecognizerFactory(onAnyTapUp: onDismiss),
|
_AnyTapGestureRecognizer: _AnyTapGestureRecognizerFactory(onAnyTapUp: onDismiss, onAnyTapCancel: onDismiss),
|
||||||
};
|
};
|
||||||
|
|
||||||
return RawGestureDetector(
|
return RawGestureDetector(
|
||||||
|
@ -251,6 +251,39 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('ModalBarrier pops the Navigator when dismissed by tap cancel', (WidgetTester tester) async {
|
||||||
|
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||||
|
'/': (BuildContext context) => const FirstWidget(),
|
||||||
|
'/modal': (BuildContext context) => const SecondWidget(),
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// Press the barrier; it shouldn't dismiss yet
|
||||||
|
final TestGesture gesture = await tester.press(
|
||||||
|
find.byKey(const ValueKey<String>('barrier')),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle(); // begin transition
|
||||||
|
expect(find.byKey(const ValueKey<String>('barrier')), findsOneWidget);
|
||||||
|
|
||||||
|
// Cancel the pointer; the barrier should be dismissed
|
||||||
|
await gesture.cancel();
|
||||||
|
await tester.pumpAndSettle(const Duration(seconds: 1)); // end transition
|
||||||
|
expect(
|
||||||
|
find.byKey(const ValueKey<String>('barrier')),
|
||||||
|
findsNothing,
|
||||||
|
reason: 'The route should have been dismissed by tapping the barrier.',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('ModalBarrier may pop the Navigator when competing with other gestures', (WidgetTester tester) async {
|
testWidgets('ModalBarrier may pop the Navigator when competing with other gestures', (WidgetTester tester) async {
|
||||||
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
|
||||||
'/': (BuildContext context) => const FirstWidget(),
|
'/': (BuildContext context) => const FirstWidget(),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user