11import 'dart:async' ;
2- import 'dart:ui' ;
32
43import 'package:flutter/material.dart' ;
4+ import 'package:flutter/rendering.dart' ;
55
66import '../generated/l10n/zulip_localizations.dart' ;
77import '../model/narrow.dart' ;
@@ -48,6 +48,9 @@ class HomePage extends StatefulWidget {
4848 HomePage .buildRoute (accountId: accountId)));
4949 }
5050
51+ static String contentSemanticsIdentifier = 'home-page-content' ;
52+ static String titleSemanticsIdentifier = 'home-page-title' ;
53+
5154 @override
5255 State <HomePage > createState () => _HomePageState ();
5356}
@@ -96,15 +99,21 @@ class _HomePageState extends State<HomePage> {
9699
97100 return Scaffold (
98101 appBar: ZulipAppBar (titleSpacing: 16 ,
99- title: Text (_currentTabTitle)),
100- body: Stack (
101- children: [
102- for (final (tab, body) in pageBodies)
103- // TODO(#535): Decide if we find it helpful to use something like
104- // [SemanticsProperties.namesRoute] to structure this UI better
105- // for screen-reader software.
106- Offstage (offstage: tab != _tab.value, child: body),
107- ]),
102+ title: Semantics (
103+ identifier: HomePage .titleSemanticsIdentifier,
104+ namesRoute: true ,
105+ child: Text (_currentTabTitle))),
106+ body: Semantics (
107+ role: SemanticsRole .tabPanel,
108+ identifier: HomePage .contentSemanticsIdentifier,
109+ container: true ,
110+ explicitChildNodes: true ,
111+ child: Stack (
112+ children: [
113+ for (final (tab, body) in pageBodies)
114+ Offstage (offstage: tab != _tab.value, child: body),
115+ ]),
116+ ),
108117 bottomNavigationBar: _BottomNavBar (tabNotifier: _tab));
109118 }
110119}
@@ -156,7 +165,7 @@ class _BottomNavBar extends StatelessWidget {
156165 onPressed: () => _showMainMenu (context, tabNotifier: tabNotifier)),
157166 ];
158167
159- return DecoratedBox (
168+ Widget result = DecoratedBox (
160169 decoration: BoxDecoration (
161170 border: Border (top: BorderSide (color: designVariables.borderBar)),
162171 color: designVariables.bgBotBar),
@@ -172,6 +181,14 @@ class _BottomNavBar extends StatelessWidget {
172181 for (final navigationBarButton in navigationBarButtons)
173182 Expanded (child: navigationBarButton),
174183 ])))));
184+
185+ result = Semantics (
186+ container: true ,
187+ explicitChildNodes: true ,
188+ role: SemanticsRole .tabBar,
189+ child: result);
190+
191+ return result;
175192 }
176193}
177194
@@ -271,7 +288,7 @@ class _NavigationBarButton extends StatelessWidget {
271288 final designVariables = DesignVariables .of (context);
272289 final color = selected ? designVariables.iconSelected : designVariables.icon;
273290
274- return AnimatedScaleOnTap (
291+ Widget result = AnimatedScaleOnTap (
275292 scaleEnd: 0.875 ,
276293 duration: const Duration (milliseconds: 100 ),
277294 child: Material (
@@ -287,21 +304,31 @@ class _NavigationBarButton extends StatelessWidget {
287304 // text wrap before getting too close to the button's edge, which is
288305 // visible on tap-down.)
289306 padding: const EdgeInsets .fromLTRB (3 , 6 , 3 , 3 ),
290- child: Semantics (
291- role: SemanticsRole .tab,
292- selected: selected,
293- child: Column (
294- spacing: 3 ,
295- mainAxisSize: MainAxisSize .min,
296- children: [
297- Icon (icon, size: 24 , color: color),
298- Flexible (
299- child: Text (
300- label,
301- style: TextStyle (fontSize: 12 , color: color, height: 12 / 12 ),
302- textAlign: TextAlign .center,
303- textScaler: MediaQuery .textScalerOf (context).clamp (maxScaleFactor: 1.5 ))),
304- ]))))));
307+ child: Column (
308+ spacing: 3 ,
309+ mainAxisSize: MainAxisSize .min,
310+ children: [
311+ Icon (icon, size: 24 , color: color),
312+ Flexible (
313+ child: Text (
314+ label,
315+ style: TextStyle (fontSize: 12 , color: color, height: 12 / 12 ),
316+ textAlign: TextAlign .center,
317+ textScaler: MediaQuery .textScalerOf (context).clamp (maxScaleFactor: 1.5 ))),
318+ ])))));
319+
320+ result = MergeSemantics (
321+ child: Semantics (
322+ role: SemanticsRole .tab,
323+ controlsNodes: {
324+ HomePage .contentSemanticsIdentifier,
325+ HomePage .titleSemanticsIdentifier,
326+ },
327+ selected: selected,
328+ onTap: onPressed,
329+ child: result));
330+
331+ return result;
305332 }
306333}
307334
0 commit comments