'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 |