mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Better error message when TextField is not in a Material (#16147)
Added a call to debugCheckHasMaterial() at the start of TextField's build method.
This commit is contained in:
parent
f069878618
commit
68728e9f98
@ -10,6 +10,7 @@ import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
import 'debug.dart';
|
||||
import 'feedback.dart';
|
||||
import 'ink_well.dart' show InteractiveInkFeature;
|
||||
import 'input_decorator.dart';
|
||||
@ -42,7 +43,9 @@ export 'package:flutter/services.dart' show TextInputType;
|
||||
/// extra padding introduced by the decoration to save space for the labels.
|
||||
///
|
||||
/// If [decoration] is non-null (which is the default), the text field requires
|
||||
/// one of its ancestors to be a [Material] widget.
|
||||
/// one of its ancestors to be a [Material] widget. When the [TextField] is
|
||||
/// tapped an ink splash that paints on the material is triggered, see
|
||||
/// [ThemeData.splashFactory].
|
||||
///
|
||||
/// To integrate the [TextField] into a [Form] with other [FormField] widgets,
|
||||
/// consider using [TextFormField].
|
||||
@ -450,6 +453,7 @@ class _TextFieldState extends State<TextField> with AutomaticKeepAliveClientMixi
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
super.build(context); // See AutomaticKeepAliveClientMixin.
|
||||
assert(debugCheckHasMaterial(context));
|
||||
final ThemeData themeData = Theme.of(context);
|
||||
final TextStyle style = widget.style ?? themeData.textTheme.subhead;
|
||||
final TextEditingController controller = _effectiveController;
|
||||
|
@ -132,14 +132,16 @@ void main() {
|
||||
return new CupertinoPageRoute<void>(
|
||||
settings: settings,
|
||||
builder: (BuildContext context) {
|
||||
return new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new TextField(
|
||||
focusNode: focusNodes[index],
|
||||
autofocus: true,
|
||||
);
|
||||
},
|
||||
return new Material(
|
||||
child: new CupertinoTabScaffold(
|
||||
tabBar: _buildTabBar(),
|
||||
tabBuilder: (BuildContext context, int index) {
|
||||
return new TextField(
|
||||
focusNode: focusNodes[index],
|
||||
autofocus: true,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -7,11 +7,11 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('TextField works correctly when changing helperText', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new MaterialApp(home: const TextField(decoration: const InputDecoration(helperText: 'Awesome'))));
|
||||
await tester.pumpWidget(new MaterialApp(home: const Material(child: const TextField(decoration: const InputDecoration(helperText: 'Awesome')))));
|
||||
expect(find.text('Awesome'), findsNWidgets(1));
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
expect(find.text('Awesome'), findsNWidgets(1));
|
||||
await tester.pumpWidget(new MaterialApp(home: const TextField(decoration: const InputDecoration(errorText: 'Awesome'))));
|
||||
await tester.pumpWidget(new MaterialApp(home: const Material(child: const TextField(decoration: const InputDecoration(errorText: 'Awesome')))));
|
||||
expect(find.text('Awesome'), findsNWidgets(2));
|
||||
});
|
||||
}
|
@ -2060,5 +2060,13 @@ void main() {
|
||||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('TextField throws when not descended from a Material widget', (WidgetTester tester) async {
|
||||
const Widget textField = const TextField();
|
||||
await tester.pumpWidget(textField);
|
||||
final dynamic exception = tester.takeException();
|
||||
expect(exception, isFlutterError);
|
||||
expect(exception.toString(), startsWith('No Material widget found.'));
|
||||
expect(exception.toString(), endsWith(':\n $textField\nThe ancestors of this widget were:\n [root]'));
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -6,15 +6,16 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
void main() {
|
||||
testWidgets('PhysicalModel - creates a physical model layer when it needs compositing', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(new Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: new PhysicalModel(
|
||||
shape: BoxShape.rectangle,
|
||||
color: Colors.grey,
|
||||
shadowColor: Colors.red,
|
||||
elevation: 1.0,
|
||||
child: new TextField(controller: new TextEditingController()),
|
||||
textDirection: TextDirection.ltr,
|
||||
child: new PhysicalModel(
|
||||
shape: BoxShape.rectangle,
|
||||
color: Colors.grey,
|
||||
shadowColor: Colors.red,
|
||||
elevation: 1.0,
|
||||
child: new Material(child: new TextField(controller: new TextEditingController())),
|
||||
),
|
||||
),
|
||||
));
|
||||
);
|
||||
await tester.pump();
|
||||
|
||||
final RenderPhysicalModel renderPhysicalModel = tester.allRenderObjects.firstWhere((RenderObject object) => object is RenderPhysicalModel);
|
||||
|
Loading…
Reference in New Issue
Block a user