Commit 5e595d12 authored by amirh's avatar amirh Committed by GitHub

Allow specifying and a11y label for Icon widget (#12475)

* Allow specifying and a11y label for Icon widget
parent c38b8434
......@@ -35,7 +35,8 @@ class Icon extends StatelessWidget {
const Icon(this.icon, {
Key key,
this.size,
this.color
this.color,
this.semanticLabel,
}) : super(key: key);
/// The icon to display. The available icons are described in [Icons].
......@@ -83,6 +84,14 @@ class Icon extends StatelessWidget {
/// ```
final Color color;
/// Semantic label for the icon.
///
/// This would be read out in accessibility modes (e.g TalkBack/VoiceOver).
/// This label does not show in the UI.
///
/// See [Semantics.label];
final String semanticLabel;
@override
Widget build(BuildContext context) {
assert(debugCheckHasDirectionality(context));
......@@ -93,27 +102,29 @@ class Icon extends StatelessWidget {
final double iconSize = size ?? iconTheme.size;
if (icon == null)
return new SizedBox(width: iconSize, height: iconSize);
return _wrapWithSemantics(new SizedBox(width: iconSize, height: iconSize));
final double iconOpacity = iconTheme.opacity;
Color iconColor = color ?? iconTheme.color;
if (iconOpacity != 1.0)
iconColor = iconColor.withOpacity(iconColor.opacity * iconOpacity);
return new ExcludeSemantics(
child: new SizedBox(
width: iconSize,
height: iconSize,
child: new Center(
child: new RichText(
textDirection: textDirection, // Since we already fetched it for the assert...
text: new TextSpan(
text: new String.fromCharCode(icon.codePoint),
style: new TextStyle(
inherit: false,
color: iconColor,
fontSize: iconSize,
fontFamily: icon.fontFamily,
return _wrapWithSemantics(
new ExcludeSemantics(
child: new SizedBox(
width: iconSize,
height: iconSize,
child: new Center(
child: new RichText(
textDirection: textDirection, // Since we already fetched it for the assert...
text: new TextSpan(
text: new String.fromCharCode(icon.codePoint),
style: new TextStyle(
inherit: false,
color: iconColor,
fontSize: iconSize,
fontFamily: icon.fontFamily,
),
),
),
),
......@@ -122,6 +133,17 @@ class Icon extends StatelessWidget {
);
}
/// Wraps the widget with a Semantics widget if [semanticLabel] is set.
Widget _wrapWithSemantics(Widget widget) {
if (semanticLabel == null)
return widget;
return new Semantics(
child: widget,
label: semanticLabel,
);
}
@override
void debugFillProperties(DiagnosticPropertiesBuilder description) {
super.debugFillProperties(description);
......
......@@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
import 'semantics_tester.dart';
void main() {
testWidgets('Can set opacity for an Icon', (WidgetTester tester) async {
await tester.pumpWidget(
......@@ -122,4 +125,40 @@ void main() {
final RichText richText = tester.firstWidget(find.byType(RichText));
expect(richText.text.style.fontFamily, equals('Roboto'));
});
testWidgets('Icon with semantic label', (WidgetTester tester) async {
final SemanticsTester semantics = new SemanticsTester(tester);
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
child: const Center(
child: const Icon(
Icons.title,
semanticLabel: 'a label',
),
),
),
);
expect(semantics, hasSemantics(new TestSemantics.root(label: 'a label')));
});
testWidgets('Null icon with semantic label', (WidgetTester tester) async {
final SemanticsTester semantics = new SemanticsTester(tester);
await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
child: const Center(
child: const Icon(
null,
semanticLabel: 'a label',
),
),
),
);
expect(semantics, hasSemantics(new TestSemantics.root(label: 'a label')));
});
}
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