@@ -26,25 +26,28 @@ class FirstComponentList extends StatelessWidget {
2626
2727 @override
2828 Widget build (BuildContext context) {
29- return ListView (
30- padding: showSecondList
31- ? const EdgeInsetsDirectional .only (end: smallSpacing)
32- : EdgeInsets .zero,
33- children: [
34- const Actions (),
35- colDivider,
36- const Communication (),
37- colDivider,
38- const Containment (),
39- if (! showSecondList) ...[
40- colDivider,
41- Navigation (scaffoldKey: scaffoldKey),
29+ // Fully traverse this list before moving on.
30+ return FocusTraversalGroup (
31+ child: ListView (
32+ padding: showSecondList
33+ ? const EdgeInsetsDirectional .only (end: smallSpacing)
34+ : EdgeInsets .zero,
35+ children: [
36+ const Actions (),
4237 colDivider,
43- const Selection (),
38+ const Communication (),
4439 colDivider,
45- const TextInputs ()
40+ const Containment (),
41+ if (! showSecondList) ...[
42+ colDivider,
43+ Navigation (scaffoldKey: scaffoldKey),
44+ colDivider,
45+ const Selection (),
46+ colDivider,
47+ const TextInputs ()
48+ ],
4649 ],
47- ] ,
50+ ) ,
4851 );
4952 }
5053}
@@ -59,15 +62,18 @@ class SecondComponentList extends StatelessWidget {
5962
6063 @override
6164 Widget build (BuildContext context) {
62- return ListView (
63- padding: const EdgeInsetsDirectional .only (end: smallSpacing),
64- children: < Widget > [
65- Navigation (scaffoldKey: scaffoldKey),
66- colDivider,
67- const Selection (),
68- colDivider,
69- const TextInputs (),
70- ],
65+ // Fully traverse this list before moving on.
66+ return FocusTraversalGroup (
67+ child: ListView (
68+ padding: const EdgeInsetsDirectional .only (end: smallSpacing),
69+ children: < Widget > [
70+ Navigation (scaffoldKey: scaffoldKey),
71+ colDivider,
72+ const Selection (),
73+ colDivider,
74+ const TextInputs (),
75+ ],
76+ ),
7177 );
7278 }
7379}
@@ -1011,13 +1017,13 @@ class NavigationBars extends StatefulWidget {
10111017 this .onSelectItem,
10121018 required this .selectedIndex,
10131019 required this .isExampleBar,
1014- this .isBadgeExample,
1020+ this .isBadgeExample = false ,
10151021 });
10161022
10171023 final void Function (int )? onSelectItem;
10181024 final int selectedIndex;
10191025 final bool isExampleBar;
1020- final bool ? isBadgeExample;
1026+ final bool isBadgeExample;
10211027
10221028 @override
10231029 State <NavigationBars > createState () => _NavigationBarsState ();
@@ -1042,23 +1048,26 @@ class _NavigationBarsState extends State<NavigationBars> {
10421048
10431049 @override
10441050 Widget build (BuildContext context) {
1045- bool isBadgeExample = widget.isBadgeExample ?? false ;
1046- Widget navigationBar = NavigationBar (
1047- selectedIndex: selectedIndex,
1048- onDestinationSelected: (index) {
1049- setState (() {
1050- selectedIndex = index;
1051- });
1052- if (! widget.isExampleBar) widget.onSelectItem !(index);
1053- },
1054- destinations: widget.isExampleBar && isBadgeExample
1055- ? barWithBadgeDestinations
1056- : widget.isExampleBar
1057- ? exampleBarDestinations
1058- : appBarDestinations,
1051+ // App NavigationBar should get first focus.
1052+ Widget navigationBar = Focus (
1053+ autofocus: ! (widget.isExampleBar || widget.isBadgeExample),
1054+ child: NavigationBar (
1055+ selectedIndex: selectedIndex,
1056+ onDestinationSelected: (index) {
1057+ setState (() {
1058+ selectedIndex = index;
1059+ });
1060+ if (! widget.isExampleBar) widget.onSelectItem !(index);
1061+ },
1062+ destinations: widget.isExampleBar && widget.isBadgeExample
1063+ ? barWithBadgeDestinations
1064+ : widget.isExampleBar
1065+ ? exampleBarDestinations
1066+ : appBarDestinations,
1067+ ),
10591068 );
10601069
1061- if (widget.isExampleBar && isBadgeExample) {
1070+ if (widget.isExampleBar && widget. isBadgeExample) {
10621071 navigationBar = ComponentDecoration (
10631072 label: 'Badges' ,
10641073 tooltipMessage: 'Use Badge or Badge.count' ,
@@ -2188,7 +2197,7 @@ class _SlidersState extends State<Sliders> {
21882197 }
21892198}
21902199
2191- class ComponentDecoration extends StatelessWidget {
2200+ class ComponentDecoration extends StatefulWidget {
21922201 const ComponentDecoration ({
21932202 super .key,
21942203 required this .label,
@@ -2200,6 +2209,13 @@ class ComponentDecoration extends StatelessWidget {
22002209 final Widget child;
22012210 final String ? tooltipMessage;
22022211
2212+ @override
2213+ State <ComponentDecoration > createState () => _ComponentDecorationState ();
2214+ }
2215+
2216+ class _ComponentDecorationState extends State <ComponentDecoration > {
2217+ final focusNode = FocusNode ();
2218+
22032219 @override
22042220 Widget build (BuildContext context) {
22052221 return RepaintBoundary (
@@ -2210,9 +2226,10 @@ class ComponentDecoration extends StatelessWidget {
22102226 Row (
22112227 mainAxisAlignment: MainAxisAlignment .center,
22122228 children: [
2213- Text (label, style: Theme .of (context).textTheme.titleSmall),
2229+ Text (widget.label,
2230+ style: Theme .of (context).textTheme.titleSmall),
22142231 Tooltip (
2215- message: tooltipMessage,
2232+ message: widget. tooltipMessage,
22162233 child: const Padding (
22172234 padding: EdgeInsets .symmetric (horizontal: 5.0 ),
22182235 child: Icon (Icons .info_outline, size: 16 )),
@@ -2222,18 +2239,32 @@ class ComponentDecoration extends StatelessWidget {
22222239 ConstrainedBox (
22232240 constraints:
22242241 const BoxConstraints .tightFor (width: widthConstraint),
2225- child: Card (
2226- elevation: 0 ,
2227- shape: RoundedRectangleBorder (
2228- side: BorderSide (
2229- color: Theme .of (context).colorScheme.outlineVariant,
2242+ // Tapping within the a component card should request focus
2243+ // for that component's children.
2244+ child: Focus (
2245+ focusNode: focusNode,
2246+ canRequestFocus: true ,
2247+ child: GestureDetector (
2248+ onTapDown: (_) {
2249+ focusNode.requestFocus ();
2250+ },
2251+ behavior: HitTestBehavior .opaque,
2252+ child: Card (
2253+ elevation: 0 ,
2254+ shape: RoundedRectangleBorder (
2255+ side: BorderSide (
2256+ color: Theme .of (context).colorScheme.outlineVariant,
2257+ ),
2258+ borderRadius: const BorderRadius .all (Radius .circular (12 )),
2259+ ),
2260+ child: Padding (
2261+ padding: const EdgeInsets .symmetric (
2262+ horizontal: 5.0 , vertical: 20.0 ),
2263+ child: Center (
2264+ child: widget.child,
2265+ ),
2266+ ),
22302267 ),
2231- borderRadius: const BorderRadius .all (Radius .circular (12 )),
2232- ),
2233- child: Padding (
2234- padding: const EdgeInsets .symmetric (
2235- horizontal: 5.0 , vertical: 20.0 ),
2236- child: Center (child: child),
22372268 ),
22382269 ),
22392270 ),
@@ -2253,19 +2284,22 @@ class ComponentGroupDecoration extends StatelessWidget {
22532284
22542285 @override
22552286 Widget build (BuildContext context) {
2256- return Card (
2257- margin: EdgeInsets .zero,
2258- elevation: 0 ,
2259- color: Theme .of (context).colorScheme.surfaceVariant.withOpacity (0.3 ),
2260- child: Padding (
2261- padding: const EdgeInsets .symmetric (vertical: 20.0 ),
2262- child: Center (
2263- child: Column (
2264- children: [
2265- Text (label, style: Theme .of (context).textTheme.titleLarge),
2266- colDivider,
2267- ...children
2268- ],
2287+ // Fully traverse this component group before moving on
2288+ return FocusTraversalGroup (
2289+ child: Card (
2290+ margin: EdgeInsets .zero,
2291+ elevation: 0 ,
2292+ color: Theme .of (context).colorScheme.surfaceVariant.withOpacity (0.3 ),
2293+ child: Padding (
2294+ padding: const EdgeInsets .symmetric (vertical: 20.0 ),
2295+ child: Center (
2296+ child: Column (
2297+ children: [
2298+ Text (label, style: Theme .of (context).textTheme.titleLarge),
2299+ colDivider,
2300+ ...children
2301+ ],
2302+ ),
22692303 ),
22702304 ),
22712305 ),
0 commit comments