mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
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.
This commit is contained in:
parent
20299a2c17
commit
3d93f24c05
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user