diff --git a/packages/flutter/lib/src/material/date_picker.dart b/packages/flutter/lib/src/material/date_picker.dart index d200b53752..81540f1f90 100644 --- a/packages/flutter/lib/src/material/date_picker.dart +++ b/packages/flutter/lib/src/material/date_picker.dart @@ -438,6 +438,7 @@ class DayPicker extends StatelessWidget { // formatted full date. label: '${localizations.formatDecimal(day)}, ${localizations.formatFullDate(dayToBuild)}', selected: isSelectedDay, + sortKey: OrdinalSortKey(day.toDouble()), child: ExcludeSemantics( child: Text(localizations.formatDecimal(day), style: itemStyle), ), diff --git a/packages/flutter/lib/src/rendering/paragraph.dart b/packages/flutter/lib/src/rendering/paragraph.dart index b0f44bb2ef..2bacd516ab 100644 --- a/packages/flutter/lib/src/rendering/paragraph.dart +++ b/packages/flutter/lib/src/rendering/paragraph.dart @@ -762,7 +762,7 @@ class RenderParagraph extends RenderBox TextDirection currentDirection = textDirection; Rect currentRect; - SemanticsConfiguration buildSemanticsConfig(int start, int end, { bool includeText = true }) { + SemanticsConfiguration buildSemanticsConfig(int start, int end) { final TextDirection initialDirection = currentDirection; final TextSelection selection = TextSelection(baseOffset: start, extentOffset: end); final List rects = getBoxesForSelection(selection); @@ -784,10 +784,8 @@ class RenderParagraph extends RenderBox order += 1; final SemanticsConfiguration configuration = SemanticsConfiguration() ..sortKey = OrdinalSortKey(order) - ..textDirection = initialDirection; - if (includeText) { - configuration.label = rawLabel.substring(start, end); - } + ..textDirection = initialDirection + ..label = rawLabel.substring(start, end); return configuration; } @@ -805,7 +803,7 @@ class RenderParagraph extends RenderBox newChildren.add(node); } final dynamic inlineElement = _inlineSemanticsElements[j]; - final SemanticsConfiguration configuration = buildSemanticsConfig(start, end, includeText: false); + final SemanticsConfiguration configuration = buildSemanticsConfig(start, end); if (inlineElement != null) { // Add semantics for this recognizer. final SemanticsNode node = SemanticsNode(); @@ -824,6 +822,9 @@ class RenderParagraph extends RenderBox } else if (childIndex < children.length) { // Add semantics for this placeholder. Semantics are precomputed in the children // argument. + // Placeholders should not get a label, which would come through as an + // object replacement character. + configuration.label = ''; final SemanticsNode childNode = children.elementAt(childIndex); final TextParentData parentData = child.parentData; childNode.rect = Rect.fromLTWH( diff --git a/packages/flutter/lib/src/semantics/semantics.dart b/packages/flutter/lib/src/semantics/semantics.dart index 799563774c..e1f57faea8 100644 --- a/packages/flutter/lib/src/semantics/semantics.dart +++ b/packages/flutter/lib/src/semantics/semantics.dart @@ -2098,7 +2098,7 @@ class SemanticsNode extends AbstractNode with DiagnosticableTreeMixin { properties.add(DoubleProperty('scrollPosition', scrollPosition, defaultValue: null)); properties.add(DoubleProperty('scrollExtentMax', scrollExtentMax, defaultValue: null)); properties.add(DoubleProperty('elevation', elevation, defaultValue: 0.0)); - properties.add(DoubleProperty('thicknes', thickness, defaultValue: 0.0)); + properties.add(DoubleProperty('thickness', thickness, defaultValue: 0.0)); } /// Returns a string representation of this node and its descendants. diff --git a/packages/flutter/pubspec.yaml b/packages/flutter/pubspec.yaml index e4afaebfe5..e27eabeae1 100644 --- a/packages/flutter/pubspec.yaml +++ b/packages/flutter/pubspec.yaml @@ -5,7 +5,7 @@ homepage: http://flutter.dev environment: # The pub client defaults to an <2.0.0 sdk constraint which we need to explicitly overwrite. - sdk: ">=2.2.0 <3.0.0" + sdk: ">=2.2.2 <3.0.0" dependencies: # To update these, use "flutter update-packages --force-upgrade". diff --git a/packages/flutter/test/material/date_picker_test.dart b/packages/flutter/test/material/date_picker_test.dart index 06799ba2d9..bb5cbf6f7e 100644 --- a/packages/flutter/test/material/date_picker_test.dart +++ b/packages/flutter/test/material/date_picker_test.dart @@ -449,6 +449,7 @@ void _tests() { TestSemantics( children: [ TestSemantics( + id: 55, actions: [SemanticsAction.scrollLeft, SemanticsAction.scrollRight], children: [ TestSemantics( @@ -456,7 +457,22 @@ void _tests() { TestSemantics( children: [ TestSemantics( + id: 11, + flags: [SemanticsFlag.hasImplicitScrolling], children: [ + // TODO(dnfield): These shouldn't be here. https://github.com/flutter/flutter/issues/34431 + TestSemantics(), + TestSemantics(), + TestSemantics(), + TestSemantics(), + TestSemantics(), + TestSemantics(), + TestSemantics(), + TestSemantics(), + TestSemantics(), + TestSemantics(), + TestSemantics(), + TestSemantics(), TestSemantics( actions: [SemanticsAction.tap], label: '1, Friday, January 1, 2016', diff --git a/packages/flutter/test/material/search_test.dart b/packages/flutter/test/material/search_test.dart index 6d93b34c0f..38e5ee306c 100644 --- a/packages/flutter/test/material/search_test.dart +++ b/packages/flutter/test/material/search_test.dart @@ -530,7 +530,7 @@ void main() { SemanticsFlag.isTextField, SemanticsFlag.isFocused, SemanticsFlag.isHeader, - SemanticsFlag.namesRoute, + if (debugDefaultTargetPlatformOverride != TargetPlatform.iOS) SemanticsFlag.namesRoute, ], actions: [ SemanticsAction.tap, @@ -539,6 +539,7 @@ void main() { ], label: 'Search', textDirection: TextDirection.ltr, + textSelection: const TextSelection(baseOffset: 0, extentOffset: 0), ), ], ), diff --git a/packages/flutter/test/semantics/semantics_test.dart b/packages/flutter/test/semantics/semantics_test.dart index 7526eedfd1..87dafe8796 100644 --- a/packages/flutter/test/semantics/semantics_test.dart +++ b/packages/flutter/test/semantics/semantics_test.dart @@ -353,7 +353,7 @@ void main() { ' scrollPosition: null\n' ' scrollExtentMax: null\n' ' elevation: 0.0\n' - ' thicknes: 0.0\n', + ' thickness: 0.0\n', ); final SemanticsConfiguration config = SemanticsConfiguration() @@ -448,7 +448,7 @@ void main() { ' scrollPosition: null\n' ' scrollExtentMax: null\n' ' elevation: 0.0\n' - ' thicknes: 0.0\n', + ' thickness: 0.0\n', ); }); diff --git a/packages/flutter/test/widgets/semantics_tester.dart b/packages/flutter/test/widgets/semantics_tester.dart index 609205ae37..151a6eb131 100644 --- a/packages/flutter/test/widgets/semantics_tester.dart +++ b/packages/flutter/test/widgets/semantics_tester.dart @@ -335,7 +335,9 @@ class TestSemantics { result = false; return false; } - return true; + } + if (it.moveNext()) { + return false; } return result; } @@ -603,7 +605,6 @@ class SemanticsTester { buf.writeln(' hint: \'${node.hint}\','); if (node.textDirection != null) buf.writeln(' textDirection: ${node.textDirection},'); - if (node.hasChildren) { buf.writeln(' children: ['); for (final SemanticsNode child in node.debugListChildrenInOrder(childOrder)) { diff --git a/packages/flutter/test/widgets/semantics_tester_test.dart b/packages/flutter/test/widgets/semantics_tester_test.dart new file mode 100644 index 0000000000..ce2397dd0c --- /dev/null +++ b/packages/flutter/test/widgets/semantics_tester_test.dart @@ -0,0 +1,44 @@ +// Copyright 2019 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter/gestures.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'semantics_tester.dart'; + +void main() { + testWidgets('Semantics tester visits last child', (WidgetTester tester) async { + final SemanticsTester semantics = SemanticsTester(tester); + const TextStyle textStyle = TextStyle(fontFamily: 'Ahem'); + await tester.pumpWidget( + Text.rich( + TextSpan( + children: [ + const TextSpan(text: 'hello'), + TextSpan(text: 'world', recognizer: TapGestureRecognizer()..onTap = () { }), + ], + style: textStyle, + ), + textDirection: TextDirection.ltr, + maxLines: 1, + ), + ); + final TestSemantics expectedSemantics = TestSemantics.root( + children: [ + TestSemantics.rootChild( + children: [ + TestSemantics( + label: 'hello', + textDirection: TextDirection.ltr, + ), + TestSemantics(), + ], + ), + ], + ); + expect(semantics, isNot(hasSemantics(expectedSemantics, ignoreTransform: true, ignoreId: true, ignoreRect: true))); + semantics.dispose(); + }); +} diff --git a/packages/flutter/test/widgets/semantics_traversal_test.dart b/packages/flutter/test/widgets/semantics_traversal_test.dart index 1c182a04a3..970cb8ecff 100644 --- a/packages/flutter/test/widgets/semantics_traversal_test.dart +++ b/packages/flutter/test/widgets/semantics_traversal_test.dart @@ -152,11 +152,11 @@ void main() { // ┌─────────────────┘ // V // ┌───┐ ┌─────────┐ ┌───┐ - // │ E │ │ │>│ H │ - // └───┘ │ G │ └───┘ - // V │ │ V + // │ E │>│ │>│ G │ + // └───┘ │ F │ └───┘ + // ┌───|─────────|───┘ // ┌───┐ │ │ ┌───┐ - // │ F │>│ │ │ I │ + // │ H │─|─────────|>│ I │ // └───┘ └─────────┘ └───┘ // ┌─────────────────┘ // V @@ -171,11 +171,11 @@ void main() { // └─────────────────┐ // V // ┌───┐ ┌─────────┐ ┌───┐ - // │ E │<│ │ │ H │ - // └───┘ │ G │ └───┘ - // V │ │ V + // │ E │<│ │<│ G │ + // └───┘ │ F │ └───┘ + // └──|─────────|────┐ // ┌───┐ │ │ ┌───┐ - // │ F │ │ │<│ I │ + // │ H │<|─────────|─│ I │ // └───┘ └─────────┘ └───┘ // └─────────────────┐ // V @@ -189,9 +189,9 @@ void main() { 'C': const Offset(40.0, 0.0) & tenByTen, 'D': const Offset(60.0, 0.0) & tenByTen, 'E': const Offset(0.0, 20.0) & tenByTen, - 'F': const Offset(0.0, 40.0) & tenByTen, - 'G': const Offset(20.0, 20.0) & (tenByTen * 2.0), - 'H': const Offset(60.0, 20.0) & tenByTen, + 'F': const Offset(20.0, 20.0) & (tenByTen * 2.0), + 'G': const Offset(60.0, 20.0) & tenByTen, + 'H': const Offset(0.0, 40.0) & tenByTen, 'I': const Offset(60.0, 40.0) & tenByTen, 'J': const Offset(0.0, 60.0) & tenByTen, 'K': const Offset(20.0, 60.0) & tenByTen, @@ -208,7 +208,7 @@ void main() { await tester.test( textDirection: TextDirection.rtl, children: children, - expectedTraversal: 'D C B A H I G E F M L K J', + expectedTraversal: 'D C B A G F E I H M L K J', ); }); diff --git a/packages/flutter/test/widgets/sliver_semantics_test.dart b/packages/flutter/test/widgets/sliver_semantics_test.dart index 1ad33d7853..5e6dbdc6a9 100644 --- a/packages/flutter/test/widgets/sliver_semantics_test.dart +++ b/packages/flutter/test/widgets/sliver_semantics_test.dart @@ -168,6 +168,7 @@ void _tests() { SemanticsAction.scrollUp, SemanticsAction.scrollDown, ], + flags: [SemanticsFlag.hasImplicitScrolling], children: [ TestSemantics( id: 3, @@ -521,6 +522,7 @@ void _tests() { SemanticsAction.scrollUp, SemanticsAction.scrollDown, ], + flags: [SemanticsFlag.hasImplicitScrolling], children: [ TestSemantics( flags: [SemanticsFlag.isHidden], @@ -630,6 +632,7 @@ void _tests() { SemanticsAction.scrollUp, SemanticsAction.scrollDown, ], + flags: [SemanticsFlag.hasImplicitScrolling], children: [ TestSemantics( flags: [SemanticsFlag.isHidden], @@ -994,6 +997,7 @@ void _tests() { SemanticsAction.scrollUp, SemanticsAction.scrollDown, ], + flags: [SemanticsFlag.hasImplicitScrolling], children: [ TestSemantics( flags: [SemanticsFlag.isHidden], diff --git a/packages/flutter/test/widgets/text_test.dart b/packages/flutter/test/widgets/text_test.dart index 55f039a86c..eec4761744 100644 --- a/packages/flutter/test/widgets/text_test.dart +++ b/packages/flutter/test/widgets/text_test.dart @@ -218,7 +218,7 @@ void main() { ], ), TestSemantics( - label: ' regrettable event', + label: ' this is a regrettable event', textDirection: TextDirection.ltr, ), ], @@ -414,7 +414,7 @@ void main() { TestSemantics( label: 'INTERRUPTION', textDirection: TextDirection.rtl, - rect: const Rect.fromLTRB(448.0, 0.0, 488.0, 80.0), + rect: const Rect.fromLTRB(0.0, 0.0, 40.0, 80.0), ), TestSemantics( label: 'sky',