@@ -1548,6 +1548,7 @@ class SubmenuButton extends StatefulWidget {
1548
1548
this .onFocusChange,
1549
1549
this .onOpen,
1550
1550
this .onClose,
1551
+ this .controller,
1551
1552
this .style,
1552
1553
this .menuStyle,
1553
1554
this .alignmentOffset,
@@ -1578,6 +1579,9 @@ class SubmenuButton extends StatefulWidget {
1578
1579
/// A callback that is invoked when the menu is closed.
1579
1580
final VoidCallback ? onClose;
1580
1581
1582
+ /// An optional [MenuController] for this submenu.
1583
+ final MenuController ? controller;
1584
+
1581
1585
/// Customizes this button's appearance.
1582
1586
///
1583
1587
/// Non-null properties of this style override the corresponding properties in
@@ -1760,7 +1764,8 @@ class SubmenuButton extends StatefulWidget {
1760
1764
class _SubmenuButtonState extends State <SubmenuButton > {
1761
1765
FocusNode ? _internalFocusNode;
1762
1766
bool _waitingToFocusMenu = false ;
1763
- final MenuController _menuController = MenuController ();
1767
+ MenuController ? _internalMenuController;
1768
+ MenuController get _menuController => widget.controller ?? _internalMenuController! ;
1764
1769
_MenuAnchorState ? get _anchor => _MenuAnchorState ._maybeOf (context);
1765
1770
FocusNode get _buttonFocusNode => widget.focusNode ?? _internalFocusNode! ;
1766
1771
bool get _enabled => widget.menuChildren.isNotEmpty;
@@ -1777,12 +1782,15 @@ class _SubmenuButtonState extends State<SubmenuButton> {
1777
1782
return true ;
1778
1783
}());
1779
1784
}
1785
+ if (widget.controller == null ) {
1786
+ _internalMenuController = MenuController ();
1787
+ }
1780
1788
_buttonFocusNode.addListener (_handleFocusChange);
1781
1789
}
1782
1790
1783
1791
@override
1784
1792
void dispose () {
1785
- _internalFocusNode ? .removeListener (_handleFocusChange);
1793
+ _buttonFocusNode .removeListener (_handleFocusChange);
1786
1794
_internalFocusNode? .dispose ();
1787
1795
_internalFocusNode = null ;
1788
1796
super .dispose ();
@@ -1810,6 +1818,9 @@ class _SubmenuButtonState extends State<SubmenuButton> {
1810
1818
}
1811
1819
_buttonFocusNode.addListener (_handleFocusChange);
1812
1820
}
1821
+ if (widget.controller != oldWidget.controller) {
1822
+ _internalMenuController = (oldWidget.controller == null ) ? null : MenuController ();
1823
+ }
1813
1824
}
1814
1825
1815
1826
@override
@@ -1836,7 +1847,16 @@ class _SubmenuButtonState extends State<SubmenuButton> {
1836
1847
alignmentOffset: menuPaddingOffset,
1837
1848
clipBehavior: widget.clipBehavior,
1838
1849
onClose: widget.onClose,
1839
- onOpen: widget.onOpen,
1850
+ onOpen: () {
1851
+ if (! _waitingToFocusMenu) {
1852
+ SchedulerBinding .instance.addPostFrameCallback ((_) {
1853
+ _menuController._anchor? ._focusButton ();
1854
+ _waitingToFocusMenu = false ;
1855
+ });
1856
+ _waitingToFocusMenu = true ;
1857
+ }
1858
+ widget.onOpen? .call ();
1859
+ },
1840
1860
style: widget.menuStyle,
1841
1861
builder: (BuildContext context, MenuController controller, Widget ? child) {
1842
1862
// Since we don't want to use the theme style or default style from the
@@ -1857,16 +1877,6 @@ class _SubmenuButtonState extends State<SubmenuButton> {
1857
1877
controller.close ();
1858
1878
} else {
1859
1879
controller.open ();
1860
- if (! _waitingToFocusMenu) {
1861
- // Only schedule this if it's not already scheduled.
1862
- SchedulerBinding .instance.addPostFrameCallback ((Duration _) {
1863
- // This has to happen in the next frame because the menu bar is
1864
- // not focusable until the first menu is open.
1865
- controller._anchor? ._focusButton ();
1866
- _waitingToFocusMenu = false ;
1867
- });
1868
- _waitingToFocusMenu = true ;
1869
- }
1870
1880
}
1871
1881
}
1872
1882
0 commit comments