[Material] Allow Appbar to exclude header semantics (#52894)
This commit is contained in:
parent
bbc9d4f3a6
commit
e2610a450c
@ -193,6 +193,7 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
this.textTheme,
|
||||
this.primary = true,
|
||||
this.centerTitle,
|
||||
this.excludeHeaderSemantics = false,
|
||||
this.titleSpacing = NavigationToolbar.kMiddleSpacing,
|
||||
this.toolbarOpacity = 1.0,
|
||||
this.bottomOpacity = 1.0,
|
||||
@ -387,6 +388,11 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
|
||||
/// Defaults to being adapted to the current [TargetPlatform].
|
||||
final bool centerTitle;
|
||||
|
||||
/// Whether the title should be wrapped with header [Semantics].
|
||||
///
|
||||
/// Defaults to false.
|
||||
final bool excludeHeaderSemantics;
|
||||
|
||||
/// The spacing around [title] content on the horizontal axis. This spacing is
|
||||
/// applied even if there is no [leading] content or [actions]. If you want
|
||||
/// [title] to take all the space available, set this value to 0.0.
|
||||
@ -526,15 +532,21 @@ class _AppBarState extends State<AppBar> {
|
||||
case TargetPlatform.macOS:
|
||||
break;
|
||||
}
|
||||
|
||||
title = _AppBarTitleBox(child: title);
|
||||
if (!widget.excludeHeaderSemantics) {
|
||||
title = Semantics(
|
||||
namesRoute: namesRoute,
|
||||
child: title,
|
||||
header: true,
|
||||
);
|
||||
}
|
||||
|
||||
title = DefaultTextStyle(
|
||||
style: centerStyle,
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
child: Semantics(
|
||||
namesRoute: namesRoute,
|
||||
child: _AppBarTitleBox(child: title),
|
||||
header: true,
|
||||
),
|
||||
child: title,
|
||||
);
|
||||
}
|
||||
|
||||
@ -725,6 +737,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
||||
@required this.textTheme,
|
||||
@required this.primary,
|
||||
@required this.centerTitle,
|
||||
@required this.excludeHeaderSemantics,
|
||||
@required this.titleSpacing,
|
||||
@required this.expandedHeight,
|
||||
@required this.collapsedHeight,
|
||||
@ -752,6 +765,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
||||
final TextTheme textTheme;
|
||||
final bool primary;
|
||||
final bool centerTitle;
|
||||
final bool excludeHeaderSemantics;
|
||||
final double titleSpacing;
|
||||
final double expandedHeight;
|
||||
final double collapsedHeight;
|
||||
@ -803,7 +817,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
||||
automaticallyImplyLeading: automaticallyImplyLeading,
|
||||
title: title,
|
||||
actions: actions,
|
||||
flexibleSpace: (title == null && flexibleSpace != null)
|
||||
flexibleSpace: (title == null && flexibleSpace != null && !excludeHeaderSemantics)
|
||||
? Semantics(child: flexibleSpace, header: true)
|
||||
: flexibleSpace,
|
||||
bottom: bottom,
|
||||
@ -815,6 +829,7 @@ class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
|
||||
textTheme: textTheme,
|
||||
primary: primary,
|
||||
centerTitle: centerTitle,
|
||||
excludeHeaderSemantics: excludeHeaderSemantics,
|
||||
titleSpacing: titleSpacing,
|
||||
shape: shape,
|
||||
toolbarOpacity: toolbarOpacity,
|
||||
@ -956,6 +971,7 @@ class SliverAppBar extends StatefulWidget {
|
||||
this.textTheme,
|
||||
this.primary = true,
|
||||
this.centerTitle,
|
||||
this.excludeHeaderSemantics = false,
|
||||
this.titleSpacing = NavigationToolbar.kMiddleSpacing,
|
||||
this.expandedHeight,
|
||||
this.floating = false,
|
||||
@ -1120,6 +1136,11 @@ class SliverAppBar extends StatefulWidget {
|
||||
/// Defaults to being adapted to the current [TargetPlatform].
|
||||
final bool centerTitle;
|
||||
|
||||
/// Whether the title should be wrapped with header [Semantics].
|
||||
///
|
||||
/// Defaults to false.
|
||||
final bool excludeHeaderSemantics;
|
||||
|
||||
/// The spacing around [title] content on the horizontal axis. This spacing is
|
||||
/// applied even if there is no [leading] content or [actions]. If you want
|
||||
/// [title] to take all the space available, set this value to 0.0.
|
||||
@ -1309,6 +1330,7 @@ class _SliverAppBarState extends State<SliverAppBar> with TickerProviderStateMix
|
||||
textTheme: widget.textTheme,
|
||||
primary: widget.primary,
|
||||
centerTitle: widget.centerTitle,
|
||||
excludeHeaderSemantics: widget.excludeHeaderSemantics,
|
||||
titleSpacing: widget.titleSpacing,
|
||||
expandedHeight: widget.expandedHeight,
|
||||
collapsedHeight: collapsedHeight,
|
||||
|
@ -1432,6 +1432,120 @@ void main() {
|
||||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('AppBar excludes header semantics correctly', (WidgetTester tester) async {
|
||||
final SemanticsTester semantics = SemanticsTester(tester);
|
||||
|
||||
await tester.pumpWidget(
|
||||
MaterialApp(
|
||||
home: Center(
|
||||
child: AppBar(
|
||||
leading: const Text('Leading'),
|
||||
title: const ExcludeSemantics(child: Text('Title')),
|
||||
excludeHeaderSemantics: true,
|
||||
actions: const <Widget>[
|
||||
Text('Action 1'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(semantics, hasSemantics(
|
||||
TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
label: 'Leading',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
TestSemantics(
|
||||
label: 'Action 1',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
ignoreRect: true,
|
||||
ignoreTransform: true,
|
||||
ignoreId: true,
|
||||
));
|
||||
|
||||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('SliverAppBar excludes header semantics correctly', (WidgetTester tester) async {
|
||||
final SemanticsTester semantics = SemanticsTester(tester);
|
||||
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: CustomScrollView(
|
||||
slivers: <Widget>[
|
||||
SliverAppBar(
|
||||
leading: Text('Leading'),
|
||||
flexibleSpace: ExcludeSemantics(child: Text('Title')),
|
||||
actions: <Widget>[Text('Action 1')],
|
||||
excludeHeaderSemantics: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(semantics, hasSemantics(
|
||||
TestSemantics.root(
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
textDirection: TextDirection.ltr,
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
flags: <SemanticsFlag>[SemanticsFlag.scopesRoute],
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
flags: <SemanticsFlag>[SemanticsFlag.hasImplicitScrolling],
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
children: <TestSemantics>[
|
||||
TestSemantics(
|
||||
label: 'Leading',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
TestSemantics(
|
||||
label: 'Action 1',
|
||||
textDirection: TextDirection.ltr,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
ignoreRect: true,
|
||||
ignoreTransform: true,
|
||||
ignoreId: true,
|
||||
));
|
||||
|
||||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('AppBar draws a light system bar for a dark background', (WidgetTester tester) async {
|
||||
final ThemeData darkTheme = ThemeData.dark();
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
|
Loading…
x
Reference in New Issue
Block a user