You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 06:23:26