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

Flutter自助终端应用:SystemChrome.setSystemUIChangeCallback在导航栏显示时未触发

问题解决:Flutter自助终端滑动调出导航栏后自动隐藏失效

问题原因

SystemChrome.setSystemUIChangeCallback 在**沉浸式粘性模式(immersiveSticky)**下存在局限性:当用户滑动调出临时显示的系统栏时,系统不会触发该回调(因为系统将其视为临时状态,不通知应用),导致你无法捕获导航栏显示的事件。

解决方案

方案1:定时检查系统栏状态(简单兼容)

通过定时任务周期性检查当前系统UI模式,若偏离沉浸式粘性模式则重新设置,适合快速解决问题:

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

class MyHomePageState extends State<MyHomePage> {
  Timer? _systemBarWatcher;

  @override
  void initState() {
    super.initState();
    _hideSystemBars();
    _startSystemBarWatcher();
  }

  @override
  void dispose() {
    _systemBarWatcher?.cancel();
    super.dispose();
  }

  Future<void> _hideSystemBars() async {
    await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
  }

  void _startSystemBarWatcher() {
    // 每隔300ms检查一次系统栏状态
    _systemBarWatcher = Timer.periodic(
      const Duration(milliseconds: 300),
      (timer) async {
        final currentMode = await SystemChrome.getEnabledSystemUIMode();
        if (currentMode != SystemUiMode.immersiveSticky) {
          await _hideSystemBars();
        }
      },
    );
  }
}

方案2:监听窗口Metrics变化(跨平台优雅方案)

利用Flutter的WidgetsBindingObserver监听窗口布局变化,系统栏显示/隐藏时会触发窗口Metrics更新,以此判断并重新隐藏系统栏:

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

class MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
  @override
  void initState() {
    super.initState();
    WidgetsBinding.instance.addObserver(this);
    _hideSystemBars();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangeMetrics() {
    super.didChangeMetrics();
    // 延迟100ms确保系统栏状态稳定后再检查
    Future.delayed(const Duration(milliseconds: 100), () async {
      final currentMode = await SystemChrome.getEnabledSystemUIMode();
      if (currentMode != SystemUiMode.immersiveSticky) {
        await _hideSystemBars();
      }
    });
  }

  Future<void> _hideSystemBars() async {
    await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky);
  }
}

方案3:Android原生监听(最可靠,仅针对Android终端)

自助终端通常基于Android系统,直接在原生层监听系统UI变化,能做到无延迟响应:

Android端(MainActivity.kt):

import android.os.Bundle
import android.view.View
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.your.package/kiosk"

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "hideSystemBars" -> {
                    hideSystemBars()
                    result.success(null)
                }
            }
        }

        // 监听系统UI可见性变化
        window.decorView.setOnSystemUiVisibilityChangeListener { visibility ->
            if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
                // 系统栏已显示,立即隐藏
                hideSystemBars()
            }
        }
    }

    private fun hideSystemBars() {
        window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                or View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
    }

    override fun onResume() {
        super.onResume()
        hideSystemBars()
    }
}

Flutter端:

import 'package:flutter/services.dart';

class MyHomePageState extends State<MyHomePage> {
  static const MethodChannel _channel = MethodChannel('com.your.package/kiosk');

  @override
  void initState() {
    super.initState();
    _hideSystemBars();
  }

  Future<void> _hideSystemBars() async {
    try {
      await _channel.invokeMethod('hideSystemBars');
    } on PlatformException catch (e) {
      print("隐藏系统栏失败: ${e.message}");
    }
  }
}

方案选择

  • 跨平台应用优先选方案2,兼顾优雅性和兼容性;
  • 仅Android终端推荐方案3,响应无延迟,稳定性最高;
  • 快速验证可选方案1,实现成本最低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.09 13:04:51