I have a form that uses FocusNode
s to visually indicate which part of the form is active. One field extends a PopupRoute as a kind of pop up 'keyboard'. My problem is, when I press that field, the keyboard pops up but the visual effect of the focus doesn't occur.
Some debugging from the FocusNode
's listeners shows it gets focus but immediately loses it. I think it is because the new PopupRoute
has a new FocusScopeNode
, so my FocusNode
doesn't have focus any more.
How can I keep the field focused while in the other route? I've tried:
FocusScope.of(context).reparentIfNeeded(focusNode)
in all the build methods, which didn't do anything (I don't really understand this function tbh)FocusScope.of(context)
into my custom PopupRoute
to use. This actually worked, but after it's popped, I can't focus anything anymore (I guess it gets disposed?)Code-wise, I'm calling requestFocus
on the field tap, and adding this listener in initState:
widget.focusNode.addListener(() {
print(widget.focusNode);
if (widget.focusNode.hasFocus) {
Navigator.of(context).push(
CustomKeyboardPopupRoute(
state: widget.state,
position: //position stuff,
focusScopeNode: FocusScope.of(context), //the second of my ideas which didn't quite work above
)
).then((_) {
widget.focusNode.unfocus();
});
});
You are on the right track, indeed this happens because of the FocusScopeNode
.
Make your keyboard route extend TransitionRoute
:
class CustomKeyboardPopupRoute extends TransitionRoute {
@override
bool get opaque => false;
@override
Duration get transitionDuration => Duration(milliseconds: 300);
@override
Iterable<OverlayEntry> createOverlayEntries() sync* {
yield OverlayEntry(
opaque: false,
maintainState: true,
builder: _buildKeyboard,
);
}
Widget _buildKeyboard(BuildContext context) {
final positionAnimation = Tween(begin: Offset(0.0, 1.0), end: Offset.zero).animate(animation);
return SlideTransition(position: positionAnimation, child: Align(
alignment: Alignment.bottomCenter,
child: ...
),);
}
}