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

如何检测Flutter应用是否全屏?含分屏/Stage Manager场景

检测Flutter应用是否处于全屏状态(防作弊场景)

核心思路

要判断应用是否处于全屏(排除Split View、iOS Stage Manager、窗口调整等作弊可能),关键是获取设备真实屏幕尺寸,并与当前应用窗口尺寸对比。同时覆盖初始化、尺寸变化、生命周期恢复等所有可能的场景,确保任何非全屏状态都能被检测到。


1. 获取设备真实屏幕尺寸

MediaQuery.of(context).size返回的是应用窗口的尺寸,而非设备完整屏幕尺寸。可以通过Flutter内置的平台调度器获取物理屏幕尺寸,再转换为逻辑像素:

Size getScreenRealSize(BuildContext context) {
  final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
  final physicalSize = WidgetsBinding.instance.platformDispatcher.implicitView?.physicalSize;
  if (physicalSize == null) return Size.zero;
  // 转换为逻辑像素尺寸
  return Size(
    physicalSize.width / devicePixelRatio,
    physicalSize.height / devicePixelRatio,
  );
}

2. 判断是否全屏

对比应用窗口尺寸与真实屏幕尺寸,允许1像素的误差(适配系统UI的细微差异):

bool isFullScreen(BuildContext context) {
  final appSize = MediaQuery.of(context).size;
  final screenSize = getScreenRealSize(context);
  
  final widthMatch = (appSize.width - screenSize.width).abs() < 1;
  final heightMatch = (appSize.height - screenSize.height).abs() < 1;
  
  return widthMatch && heightMatch;
}

3. 覆盖所有检测场景

(1)测试场景初始化时检测

用户可能在非全屏状态进入测试,需在页面初始化时立即验证:

@override
void initState() {
  super.initState();
  WidgetsBinding.instance.addPostFrameCallback((_) {
    if (!isFullScreen(context)) {
      _triggerAntiCheatLogic();
    }
  });
}

(2)监听窗口尺寸变化

保留原有的didChangeMetrics回调,但补充全屏检测逻辑:

@override
void didChangeMetrics() {
  super.didChangeMetrics();
  WidgetsBinding.instance.addPostFrameCallback((_) {
    if (!isFullScreen(context)) {
      _triggerAntiCheatLogic();
    }
  });
}

(3)修复生命周期监听的不足

原有的didChangeAppLifecycleState无法检测Stage Manager/Slide Over(这类状态下应用仍处于resumed状态),需在恢复前台时重新检测:

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
  super.didChangeAppLifecycleState(state);
  switch (state) {
    case AppLifecycleState.resumed:
      setState(() => inBackground = false);
      // 恢复前台后立即检测全屏
      WidgetsBinding.instance.addPostFrameCallback((_) {
        if (!isFullScreen(context)) {
          _triggerAntiCheatLogic();
        }
      });
      break;
    case AppLifecycleState.inactive:
    case AppLifecycleState.paused:
    case AppLifecycleState.detached:
      setState(() => inBackground = true);
      break;
  }
}

4. 防作弊逻辑示例

检测到非全屏状态时,执行对应的限制操作:

void _triggerAntiCheatLogic() {
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (ctx) => AlertDialog(
      title: const Text('测试环境要求'),
      content: const Text('请将应用切换为全屏状态,否则无法继续测试。'),
      actions: [
        TextButton(
          onPressed: () {
            if (isFullScreen(context)) {
              Navigator.pop(ctx);
            } else {
              // 强制退出应用或终止测试流程
              SystemNavigator.pop();
            }
          },
          child: const Text('确认'),
        ),
      ],
    ),
  );
}

注意事项

  • 适配特殊设备:折叠屏、刘海屏等场景,通过1像素误差容忍可适配系统UI的细微差异;
  • 性能优化:didChangeMetrics会频繁触发,使用addPostFrameCallback确保在UI更新后再检测,避免获取旧尺寸;
  • 全平台覆盖:iOS Stage Manager/Slide Over、Android Split View等状态下,应用窗口尺寸必然小于屏幕尺寸,均可被检测到。

内容的提问来源于stack exchange,提问作者Jasper

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 19:20:12