Unverified Commit 3d93f24c authored by Darren Austin's avatar Darren Austin Committed by GitHub

Tapping a modal bottom sheet should not dismiss it by default (#32528)

Removed the GestureDetector from the modal bottom sheet that dismissed it on tap and updated several tests to accommodate this change.
parent 20299a2c
......@@ -24,7 +24,7 @@ class ModalBottomSheetDemo extends StatelessWidget {
return Container(
child: Padding(
padding: const EdgeInsets.all(32.0),
child: Text('This is the modal bottom sheet. Tap anywhere to dismiss.',
child: Text('This is the modal bottom sheet. Slide down to dismiss.',
textAlign: TextAlign.center,
style: TextStyle(
color: Theme.of(context).accentColor,
......
......@@ -281,43 +281,36 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
final String routeLabel = _getRouteLabel(localizations);
return GestureDetector(
excludeFromSemantics: true,
onTap: () {
if (widget.route.isCurrent)
Navigator.pop(context);
},
child: AnimatedBuilder(
animation: widget.route.animation,
builder: (BuildContext context, Widget child) {
// Disable the initial animation when accessible navigation is on so
// that the semantics are added to the tree at the correct time.
final double animationValue = mediaQuery.accessibleNavigation ? 1.0 : widget.route.animation.value;
return Semantics(
scopesRoute: true,
namesRoute: true,
label: routeLabel,
explicitChildNodes: true,
child: ClipRect(
child: CustomSingleChildLayout(
delegate: _ModalBottomSheetLayout(animationValue, widget.isScrollControlled),
child: BottomSheet(
animationController: widget.route._animationController,
onClosing: () {
if (widget.route.isCurrent) {
Navigator.pop(context);
}
},
builder: widget.route.builder,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
),
return AnimatedBuilder(
animation: widget.route.animation,
builder: (BuildContext context, Widget child) {
// Disable the initial animation when accessible navigation is on so
// that the semantics are added to the tree at the correct time.
final double animationValue = mediaQuery.accessibleNavigation ? 1.0 : widget.route.animation.value;
return Semantics(
scopesRoute: true,
namesRoute: true,
label: routeLabel,
explicitChildNodes: true,
child: ClipRect(
child: CustomSingleChildLayout(
delegate: _ModalBottomSheetLayout(animationValue, widget.isScrollControlled),
child: BottomSheet(
animationController: widget.route._animationController,
onClosing: () {
if (widget.route.isCurrent) {
Navigator.pop(context);
}
},
builder: widget.route.builder,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
),
),
);
},
),
),
);
},
);
}
}
......
......@@ -10,7 +10,7 @@ import 'package:flutter/gestures.dart';
import '../widgets/semantics_tester.dart';
void main() {
testWidgets('Verify that a tap dismisses a modal BottomSheet', (WidgetTester tester) async {
testWidgets('Tapping on a modal BottomSheet should not dismiss it', (WidgetTester tester) async {
BuildContext savedContext;
await tester.pumpWidget(MaterialApp(
......@@ -33,28 +33,41 @@ void main() {
showBottomSheetThenCalled = true;
});
await tester.pump(); // bottom sheet show animation starts
await tester.pump(const Duration(seconds: 1)); // animation done
await tester.pumpAndSettle();
expect(find.text('BottomSheet'), findsOneWidget);
expect(showBottomSheetThenCalled, isFalse);
// Tap on the bottom sheet itself to dismiss it.
// Tap on the bottom sheet itself, it should not be dismissed
await tester.tap(find.text('BottomSheet'));
await tester.pump(); // bottom sheet dismiss animation starts
expect(showBottomSheetThenCalled, isTrue);
await tester.pump(const Duration(seconds: 1)); // last frame of animation (sheet is entirely off-screen, but still present)
await tester.pump(const Duration(seconds: 1)); // frame after the animation (sheet has been removed)
await tester.pumpAndSettle();
expect(find.text('BottomSheet'), findsOneWidget);
expect(showBottomSheetThenCalled, isFalse);
});
testWidgets('Tapping outside a modal BottomSheet should dismiss it', (WidgetTester tester) async {
BuildContext savedContext;
await tester.pumpWidget(MaterialApp(
home: Builder(
builder: (BuildContext context) {
savedContext = context;
return Container();
}
),
));
await tester.pump();
expect(find.text('BottomSheet'), findsNothing);
showBottomSheetThenCalled = false;
bool showBottomSheetThenCalled = false;
showModalBottomSheet<void>(
context: savedContext,
builder: (BuildContext context) => const Text('BottomSheet'),
).then<void>((void value) {
showBottomSheetThenCalled = true;
});
await tester.pump(); // bottom sheet show animation starts
await tester.pump(const Duration(seconds: 1)); // animation done
await tester.pumpAndSettle();
expect(find.text('BottomSheet'), findsOneWidget);
expect(showBottomSheetThenCalled, isFalse);
......
......@@ -406,8 +406,8 @@ void main() {
await tester.pumpAndSettle();
expect(find.text('modal bottom sheet'), findsOneWidget);
// Dismiss the modal bottomSheet
await tester.tap(find.text('modal bottom sheet'));
// Dismiss the modal bottomSheet by tapping above the sheet
await tester.tapAt(const Offset(20.0, 20.0));
await tester.pumpAndSettle();
expect(find.text('modal bottom sheet'), findsNothing);
expect(find.text('showModalBottomSheet'), findsOneWidget);
......
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