Unverified Commit bf7c2709 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

Make helper and error text separate widgets, make error and counter live region (#21752)

parent f8c50ea1
......@@ -320,32 +320,39 @@ class _HelperErrorState extends State<_HelperError> with SingleTickerProviderSta
Widget _buildHelper() {
assert(widget.helperText != null);
return Opacity(
opacity: 1.0 - _controller.value,
child: Text(
widget.helperText,
style: widget.helperStyle,
textAlign: widget.textAlign,
overflow: TextOverflow.ellipsis,
return Semantics(
container: true,
child: Opacity(
opacity: 1.0 - _controller.value,
child: Text(
widget.helperText,
style: widget.helperStyle,
textAlign: widget.textAlign,
overflow: TextOverflow.ellipsis,
),
),
);
}
Widget _buildError() {
assert(widget.errorText != null);
return Opacity(
opacity: _controller.value,
child: FractionalTranslation(
translation: Tween<Offset>(
begin: const Offset(0.0, -0.25),
end: const Offset(0.0, 0.0),
).evaluate(_controller.view),
child: Text(
widget.errorText,
style: widget.errorStyle,
textAlign: widget.textAlign,
overflow: TextOverflow.ellipsis,
maxLines: widget.errorMaxLines,
return Semantics(
container: true,
liveRegion: true,
child: Opacity(
opacity: _controller.value,
child: FractionalTranslation(
translation: Tween<Offset>(
begin: const Offset(0.0, -0.25),
end: const Offset(0.0, 0.0),
).evaluate(_controller.view),
child: Text(
widget.errorText,
style: widget.errorStyle,
textAlign: widget.textAlign,
overflow: TextOverflow.ellipsis,
maxLines: widget.errorMaxLines,
),
),
),
);
......@@ -1815,6 +1822,7 @@ class _InputDecoratorState extends State<InputDecorator> with TickerProviderStat
final Widget counter = decoration.counterText == null ? null :
Semantics(
container: true,
liveRegion: isFocused,
child: Text(
decoration.counterText,
style: _getHelperStyle(themeData).merge(decoration.counterStyle),
......
......@@ -2843,7 +2843,7 @@ void main() {
expect(semantics, hasSemantics(TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
label: 'label\nhelper',
label: 'label',
id: 1,
textDirection: TextDirection.ltr,
actions: <SemanticsAction>[
......@@ -2855,6 +2855,11 @@ void main() {
children: <TestSemantics>[
TestSemantics(
id: 2,
label: 'helper',
textDirection: TextDirection.ltr,
),
TestSemantics(
id: 3,
label: '10 characters remaining',
textDirection: TextDirection.ltr,
),
......@@ -2869,7 +2874,7 @@ void main() {
expect(semantics, hasSemantics(TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
label: 'hint\nhelper',
label: 'hint',
id: 1,
textDirection: TextDirection.ltr,
textSelection: const TextSelection(baseOffset: 0, extentOffset: 0),
......@@ -2885,7 +2890,15 @@ void main() {
children: <TestSemantics>[
TestSemantics(
id: 2,
label: 'helper',
textDirection: TextDirection.ltr,
),
TestSemantics(
id: 3,
label: '10 characters remaining',
flags: <SemanticsFlag>[
SemanticsFlag.isLiveRegion,
],
textDirection: TextDirection.ltr,
),
],
......@@ -2922,8 +2935,7 @@ void main() {
expect(semantics, hasSemantics(TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
label: 'label\nhelper',
id: 1,
label: 'label',
textDirection: TextDirection.ltr,
actions: <SemanticsAction>[
SemanticsAction.tap,
......@@ -2932,6 +2944,10 @@ void main() {
SemanticsFlag.isTextField,
],
children: <TestSemantics>[
TestSemantics(
label: 'helper',
textDirection: TextDirection.ltr,
),
TestSemantics(
label: '0 out of 10',
textDirection: TextDirection.ltr,
......@@ -2944,6 +2960,52 @@ void main() {
semantics.dispose();
});
testWidgets('InputDecoration errorText semantics', (WidgetTester tester) async {
final SemanticsTester semantics = SemanticsTester(tester);
final TextEditingController controller = TextEditingController();
final Key key = UniqueKey();
await tester.pumpWidget(
overlay(
child: TextField(
key: key,
controller: controller,
decoration: const InputDecoration(
labelText: 'label',
hintText: 'hint',
errorText: 'oh no!',
),
),
),
);
expect(semantics, hasSemantics(TestSemantics.root(
children: <TestSemantics>[
TestSemantics.rootChild(
label: 'label',
textDirection: TextDirection.ltr,
actions: <SemanticsAction>[
SemanticsAction.tap,
],
flags: <SemanticsFlag>[
SemanticsFlag.isTextField,
],
children: <TestSemantics>[
TestSemantics(
label: 'oh no!',
flags: <SemanticsFlag>[
SemanticsFlag.isLiveRegion,
],
textDirection: TextDirection.ltr,
),
],
),
],
), ignoreTransform: true, ignoreRect: true, ignoreId: true));
semantics.dispose();
});
testWidgets('floating label does not overlap with value at large textScaleFactors', (WidgetTester tester) async {
final TextEditingController controller = TextEditingController(text: 'Just some text');
await tester.pumpWidget(
......@@ -2964,6 +3026,7 @@ void main() {
),
),
);
await tester.tap(find.byType(TextField));
final Rect labelRect = tester.getRect(find.text('Label'));
final Rect fieldRect = tester.getRect(find.text('Just some text'));
......
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