'Change text colour of focused item in DropdownMenuButton in Flutter

The focused item in the dropdown menu is highlighted in the accent/secondary colour from the theme (example to show the highlight). However, if the highlight colour is of a different brightness than the background, the text isn't easily visible (see previous example), so I'd like to change the text colour of just the focused item. I've tried setting onSecondary to a contrasting colour in the theme's colorScheme, but the text colour of the focused dropdown menu item is not automatically changed to it. selectedItemBuilder in DropdownMenuButton seems to affect the display when the menu is closed, not the selected item in the menu. Changing the text colour in the DropdownMenuItem by comparing it to the menu's current value (eg. items: options.map((e) => DropdownMenuItem(value: e.value, child: Text(e.text, style: TextStyle(color: curr_value == e.value ? Colors.black : null)))).toList()) is insufficient because the highlight is due to the item being focused, not due to it being the selected value (this is what happens when I change the focused item using tab or arrow keys when I do that). I also tried looking through the DropdownMenuButton source code for clues, but I couldn't find where the highlight is applied. Is there a theme parameter that controls the highlighted option text colour?



Solution 1:[1]

I finally found the solution! You can use Focus.of(context) in the menu item widgets to check if they're focused. Here I have an example with a builder function being passed to a wrapper Widget that keeps track of the focus. Then, focused can be used in the builder to determine which text colour to use.

class OptionEntryItemWrapper extends StatefulWidget {
  Widget Function(BuildContext, bool) builder;

  OptionEntryItemWrapper({required this.builder});

  @override
  _OptionEntryItemWrapper createState() => _OptionEntryItemWrapper();
}

class _OptionEntryItemWrapper extends State<OptionEntryItemWrapper> {
  bool focused = false;
  FocusNode? node;

  void focus_listener() {
    if (mounted && node != null)
      setState(() {
        focused = node!.hasFocus;
      });
    ;
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    node?.removeListener(focus_listener);
    node = Focus.of(context);
    node?.addListener(focus_listener);
  }

  @override
  void dispose() {
    node?.removeListener(focus_listener);
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return widget.builder(context, focused);
  }
}

And in the items: of DropdownButton:

DropdownMenuItem(value: value, child: OptionEntryItemWrapper(builder: builder))

Solution 2:[2]

Use a boolean variable. set it to false then make a onclicked Function with help of the gesture detection widget

Onclicked(){
var= true,
}

inside the icon style write a condition:

var?backgroud.Blue:backgroud.white

(P.S. I have only written the logic Its not in right Syntax)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Zarainia
Solution 2 Shree Mahadik