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

Flutter全屏开发:隐藏Android状态栏后出现黑条问题排查

Flutter全屏组件隐藏状态栏后出现顶部黑条问题

问题现象

在OnePlus 8 Pro(Oxygen OS 13.1,Android 13)上测试Flutter全屏组件时:

  • 状态栏未隐藏时,应用占满屏幕高度,状态栏叠加在应用上方
  • 调用SystemChrome.setEnabledSystemUIMode隐藏状态栏后,状态栏图标消失,但顶部出现和状态栏高度一致的黑条
  • 底部导航栏隐藏正常
  • 测试了SafeArea、Scaffold、Container、Card等组件,问题一致

复现代码

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

enum SystemUIOptions { all, statusBar, navigationBar, immersiveSticky }

void main() {
  WidgetsFlutterBinding.ensureInitialized;
  runApp(const SystemChromeTester());
}

class SystemChromeTester extends StatefulWidget {
  const SystemChromeTester({super.key});

  @override
  State<SystemChromeTester> createState() => _SystemChromeTesterState();
}

class _SystemChromeTesterState extends State<SystemChromeTester> {
  SystemUIOptions? selectedUIOption = SystemUIOptions.all;

  void printViewInsets() {
    print('System UI option: ${selectedUIOption!.name}');
    print('Height: ${MediaQuery.of(context).size.height}');
    print('Viewinsets top: ${MediaQuery.of(context).viewInsets.top}');
    print('Viewinsets bottom: ${MediaQuery.of(context).viewInsets.bottom}');
    print('Viewpadding: ${MediaQuery.of(context).viewPadding}');
    print('Padding: ${MediaQuery.of(context).padding}');
  }

  void toggleSystemUI(SystemUIOptions? selected) {
    switch (selected) {
      case SystemUIOptions.all:
        SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
            overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]);
        break;
      case SystemUIOptions.statusBar:
        SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
            overlays: [SystemUiOverlay.top]);
        break;
      case SystemUIOptions.navigationBar:
        SystemChrome.setEnabledSystemUIMode(
          SystemUiMode.manual,
          overlays: [SystemUiOverlay.bottom],
        );
        break;
      case SystemUIOptions.immersiveSticky:
        SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
        break;
      default:
        SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
            overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]);
    }
    setState(() {
      selectedUIOption = selected;
    });
  }

  @override
  Widget build(BuildContext context) {
    printViewInsets();
    return MaterialApp(
      home: Scaffold(
        // appBar: AppBar(),
        backgroundColor: Colors.amber,
        resizeToAvoidBottomInset: false,
        body: Center(
          child: Column(
            children: [
              RadioListTile(
                title:
                    const Text('Top (status bar) and bottom (navigation bar)'),
                value: SystemUIOptions.all,
                groupValue: selectedUIOption,
                onChanged: toggleSystemUI,
              ),
              RadioListTile(
                title: const Text('Top (status bar) only'),
                value: SystemUIOptions.statusBar,
                groupValue: selectedUIOption,
                onChanged: toggleSystemUI,
              ),
              RadioListTile(
                title: const Text('Bottom (navigation bar) only'),
                value: SystemUIOptions.navigationBar,
                groupValue: selectedUIOption,
                onChanged: toggleSystemUI,
              ),
              RadioListTile(
                title: const Text('Immersive sticky'),
                value: SystemUIOptions.immersiveSticky,
                groupValue: selectedUIOption,
                onChanged: toggleSystemUI,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

问题分析

这不是Flutter的bug,属于Android 13+ 挖孔屏/刘海屏的系统适配问题:

  1. 你的设备是挖孔屏,Android 13+ 会默认保留状态栏区域的安全边距,即使隐藏了状态栏,系统也不会自动让应用内容延伸到该区域
  2. 只调用setEnabledSystemUIMode隐藏状态栏,没有配置UI覆盖样式,导致顶部区域没有被应用内容填充,显示为黑条

解决方案

需要同时配置SystemChrome.setSystemUIOverlayStyle和调整AndroidManifest.xml的主题设置:

1. 修复Flutter代码核心问题

首先修正main函数里的初始化调用(缺少括号):

void main() {
  WidgetsFlutterBinding.ensureInitialized(); // 补充括号
  runApp(const SystemChromeTester());
}

然后修改toggleSystemUI方法,在切换模式时添加UI覆盖样式配置,让应用内容延伸到状态栏区域:

void toggleSystemUI(SystemUIOptions? selected) {
  // 基础透明样式配置,让内容延伸到系统UI区域
  const baseOverlayStyle = SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    systemNavigationBarColor: Colors.transparent,
  );

  switch (selected) {
    case SystemUIOptions.all:
      SystemChrome.setSystemUIOverlayStyle(baseOverlayStyle);
      SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
          overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]);
      break;
    case SystemUIOptions.statusBar:
      SystemChrome.setSystemUIOverlayStyle(baseOverlayStyle);
      SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
          overlays: [SystemUiOverlay.top]);
      break;
    case SystemUIOptions.navigationBar:
      SystemChrome.setSystemUIOverlayStyle(baseOverlayStyle);
      SystemChrome.setEnabledSystemUIMode(
        SystemUiMode.manual,
        overlays: [SystemUiOverlay.bottom],
      );
      break;
    case SystemUIOptions.immersiveSticky:
      SystemChrome.setSystemUIOverlayStyle(const SystemUiOverlayStyle(
        statusBarColor: Colors.transparent,
        systemNavigationBarColor: Colors.transparent,
        statusBarIconBrightness: Brightness.light,
        systemNavigationBarIconBrightness: Brightness.light,
      ));
      SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky, overlays: []);
      break;
    default:
      SystemChrome.setSystemUIOverlayStyle(baseOverlayStyle);
      SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual,
          overlays: [SystemUiOverlay.top, SystemUiOverlay.bottom]);
  }
  setState(() {
    selectedUIOption = selected;
  });
}

2. Android端配置补充

在android/app/src/main/AndroidManifest.xml的Activity标签中添加挖孔屏适配属性:

<activity
    android:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTop"
    android:theme="@style/LaunchTheme"
    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
    android:hardwareAccelerated="true"
    android:windowSoftInputMode="adjustResize"
    android:windowLayoutInDisplayCutoutMode="shortEdges"> <!-- 添加此行 -->
</activity>

同时在android/app/src/main/res/values/styles.xml中确保主题为全屏:

<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item>
</style>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 09:25:04