Unverified Commit 6a48e663 authored by Dan Field's avatar Dan Field Committed by GitHub

Bottom sheet scrolling (#21896)

parent fdcc8aaf
......@@ -6,6 +6,7 @@ import 'package:flutter/widgets.dart';
import 'material.dart';
import 'material_localizations.dart';
import 'scaffold.dart' show Scaffold;
/// Asserts that the given context has a [Material] ancestor.
///
......@@ -127,3 +128,36 @@ bool debugCheckHasMaterialLocalizations(BuildContext context) {
}());
return true;
}
/// Asserts that the given context has a [Scaffold] ancestor.
///
/// Used by various widgets to make sure that they are only used in an
/// appropriate context.
///
/// To invoke this function, use the following pattern, typically in the
/// relevant Widget's build method:
///
/// ```dart
/// assert(debugCheckHasScaffold(context));
/// ```
///
/// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasScaffold(BuildContext context) {
assert(() {
if (context.widget is! Scaffold && context.ancestorWidgetOfExactType(Scaffold) == null) {
final Element element = context;
throw FlutterError(
'No Scaffold widget found.\n'
'${context.widget.runtimeType} widgets require a Scaffold widget ancestor.\n'
'The Specific widget that could not find a Scaffold ancestor was:\n'
' ${context.widget}\n'
'The ownership chain for the affected widget is:\n'
' ${element.debugGetCreatorChain(10)}\n'
'Typically, the Scaffold widget is introduced by the MaterialApp or '
'WidgetsApp widget at the top of your application widget tree.'
);
}
return true;
}());
return true;
}
......@@ -38,7 +38,7 @@ void main() {
expect(find.text('BottomSheet'), findsOneWidget);
expect(showBottomSheetThenCalled, isFalse);
// Tap on the bottom sheet itself to dismiss it
// Tap on the bottom sheet itself to dismiss it.
await tester.tap(find.text('BottomSheet'));
await tester.pump(); // bottom sheet dismiss animation starts
expect(showBottomSheetThenCalled, isTrue);
......@@ -169,6 +169,7 @@ void main() {
child: MediaQuery(
data: const MediaQueryData(
padding: EdgeInsets.all(50.0),
size: Size(400.0, 600.0),
),
child: Navigator(
onGenerateRoute: (_) {
......@@ -249,4 +250,66 @@ void main() {
), ignoreTransform: true, ignoreRect: true, ignoreId: true));
semantics.dispose();
});
testWidgets('modal BottomSheet with scrollController has semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
await tester.pumpWidget(MaterialApp(
home: Scaffold(
key: scaffoldKey,
body: const Center(child: Text('body'))
)
));
showModalBottomSheet<void>(
context: scaffoldKey.currentContext,
builder: (BuildContext context) {
return DraggableScrollableSheet(
expand: false,
builder: (_, ScrollController controller) {
return SingleChildScrollView(
controller: controller,
child: Container(
child: const Text('BottomSheet'),
),
);
},
);
},
);
await tester.pump(); // bottom sheet show animation starts
await tester.pump(const Duration(seconds: 1)); // animation done
expect(semantics, hasSemantics(TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
children: <TestSemantics>[
TestSemantics(
label: 'Dialog',
textDirection: TextDirection.ltr,
flags: <SemanticsFlag>[
SemanticsFlag.scopesRoute,
SemanticsFlag.namesRoute,
],
children: <TestSemantics>[
TestSemantics(
flags: <SemanticsFlag>[SemanticsFlag.hasImplicitScrolling],
children: <TestSemantics>[
TestSemantics(
label: 'BottomSheet',
textDirection: TextDirection.ltr,
),
],
),
],
),
],
),
],
), ignoreTransform: true, ignoreRect: true, ignoreId: true));
semantics.dispose();
});
}
......@@ -335,7 +335,6 @@ void main() {
),
),
);
await tester.tap(find.text('X'));
await tester.pump(); // start animation
await tester.pump(const Duration(seconds: 1));
......
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