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