如何让Flutter应用永久全屏?聚焦TextField后栏位复现求优雅方案
解决Flutter全屏模式下TextField获焦后系统UI无法自动隐藏的问题
当你用SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: []);设置全屏后,TextField获焦会触发系统UI重新显示且无法自动恢复,这里提供几个无需在失焦时重复调用代码的优雅解决方案:
方案一:全局焦点监听+延迟恢复全屏
利用FocusManager监听全局焦点状态,当所有焦点都失去时(比如软键盘收起、TextField失焦),延迟一小段时间再恢复全屏,避开软键盘动画的干扰:
@override void initState() { super.initState(); // 初始设置全屏 _enableFullScreen(); // 监听全局焦点变化 FocusManager.instance.addListener(_handleFocusChange); } void _enableFullScreen() { SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: []); } void _handleFocusChange() { // 确认当前无任何焦点时,延迟执行全屏设置 if (!FocusManager.instance.primaryFocus?.hasFocus ?? true) { Future.delayed(const Duration(milliseconds: 300), _enableFullScreen); } } @override void dispose() { FocusManager.instance.removeListener(_handleFocusChange); super.dispose(); }
方案二:监听窗口尺寸变化恢复全屏
软键盘弹出/收起会触发窗口尺寸变化,通过WidgetsBindingObserver监听这个事件,在尺寸稳定后恢复全屏:
@override void initState() { super.initState(); _enableFullScreen(); WidgetsBinding.instance.addObserver(_windowObserver); } final _windowObserver = _WindowMetricsObserver(); class _WindowMetricsObserver extends WidgetsBindingObserver { @override void didChangeMetrics() { super.didChangeMetrics(); // 延迟等待软键盘动画完成 Future.delayed(const Duration(milliseconds: 400), () { SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: []); }); } } @override void dispose() { WidgetsBinding.instance.removeObserver(_windowObserver); super.dispose(); }
方案三:封装全屏包裹Widget(推荐复用)
把全屏逻辑封装成独立Widget,自动处理焦点和窗口变化,直接包裹你的根应用即可:
class FullScreenWrapper extends StatefulWidget { final Widget child; const FullScreenWrapper({super.key, required this.child}); @override State<FullScreenWrapper> createState() => _FullScreenWrapperState(); } class _FullScreenWrapperState extends State<FullScreenWrapper> with WidgetsBindingObserver { @override void initState() { super.initState(); _enableFullScreen(); WidgetsBinding.instance.addObserver(this); FocusManager.instance.addListener(_handleFocusChange); } void _enableFullScreen() { SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: []); } void _handleFocusChange() { if (!FocusManager.instance.primaryFocus?.hasFocus ?? true) { Future.delayed(const Duration(milliseconds: 300), _enableFullScreen); } } @override void didChangeMetrics() { super.didChangeMetrics(); Future.delayed(const Duration(milliseconds: 400), _enableFullScreen); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); FocusManager.instance.removeListener(_handleFocusChange); super.dispose(); } @override Widget build(BuildContext context) { return widget.child; } } // 使用方式 FullScreenWrapper( child: YourRootAppWidget(), )
注意事项
- 延迟时间可根据设备实际情况调整,主要是为了等待软键盘动画完成,避免系统UI刚隐藏又被触发显示。
immersiveSticky模式下用户滑动屏幕边缘会临时唤起系统UI,几秒后自动隐藏,但TextField获焦属于系统主动触发,必须手动恢复全屏。
内容的提问来源于stack exchange,提问作者PengShilei
相关产品推荐
相关产品推荐

