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

Flutter实现后台/非活跃时用启动页隐藏应用内容(替代FLAG_SECURE黑屏)

Flutter后台显示启动页替代FLAG_SECURE黑屏的实现方案

需求说明

开发Flutter应用时,需在应用进入后台时显示启动页,替代FLAG_SECURE(Android)或模糊效果(iOS)导致的黑屏,提升用户体验。

实现方案:基于Method Channel自定义实现

Android平台修改

1. 创建启动页布局

在res/layout/下新建splash_screen.xml,添加启动页UI(示例为居中logo):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:gravity="center">

    <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:src="@drawable/app_logo" />
</LinearLayout>

2. 修改MainActivity代码

替换原有的FLAG_SECURE逻辑,改为添加/移除启动页覆盖层:

class MainActivity: FlutterFragmentActivity() {

    private val CHANNEL = "security"
    private var splashOverlay: View? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        if (intent.getIntExtra("org.chromium.chrome.extra.TASK_ID", -1) == this.taskId) {
            this.finish()
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);
        }
        super.onCreate(savedInstanceState)
    }

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        setupMethodChannel(flutterEngine)
    }

    private fun setupMethodChannel(flutterEngine: FlutterEngine) {
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler { call, result ->
            when (call.method) {
                "enableAppSecurity" -> {
                    enableAppSecurity()
                    result.success(null)
                }
                "disableAppSecurity" -> {
                    disableAppSecurity()
                    result.success(null)
                }
                else -> result.notImplemented()
            }
        }
    }

    override fun onWindowFocusChanged(hasFocus: Boolean) {
        super.onWindowFocusChanged(hasFocus)
        toggleAppSecurity(hasFocus)
    }

    override fun onPause() {
        super.onPause()
        enableAppSecurity()
    }

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

    private fun toggleAppSecurity(hasFocus: Boolean) {
        if (hasFocus) {
            disableAppSecurity()
        } else {
            enableAppSecurity()
        }
    }

    private fun enableAppSecurity() {
        if (splashOverlay == null) {
            splashOverlay = layoutInflater.inflate(R.layout.splash_screen, null)
            val params = WindowManager.LayoutParams(
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.MATCH_PARENT,
                WindowManager.LayoutParams.TYPE_APPLICATION,
                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
                PixelFormat.TRANSLUCENT
            )
            window.addContentView(splashOverlay, params)
        }
    }

    private fun disableAppSecurity() {
        splashOverlay?.let {
            (it.parent as ViewGroup).removeView(it)
            splashOverlay = null
        }
    }
}

iOS平台修改

1. 准备启动页资源

确保项目中已存在启动图资源(LaunchImage或LaunchScreen.storyboard)。

2. 修改AppDelegate代码

替换原模糊效果逻辑,改为显示启动页:

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {

    private var flutterViewController: FlutterViewController!
    private var securityChannel: FlutterMethodChannel!
    private var splashView: UIView?
    private var isInBackground: Bool = false

    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        GeneratedPluginRegistrant.register(with: self)
        setupFlutterCommunication()
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }

    private func setupFlutterCommunication() {
        flutterViewController = window?.rootViewController as? FlutterViewController
        securityChannel = FlutterMethodChannel(
            name: "security",
            binaryMessenger: flutterViewController.binaryMessenger
        )
        securityChannel.setMethodCallHandler(handle)
    }

    override func applicationDidEnterBackground(_ application: UIApplication) {
        isInBackground = true
        enableAppSecurity()
    }

    override func applicationDidBecomeActive(_ application: UIApplication) {
        if isInBackground {
            disableAppSecurity()
            isInBackground = false
        }
    }

    private func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch call.method {
        case "enableAppSecurity":
            enableAppSecurity()
            result(nil)
        case "disableAppSecurity":
            disableAppSecurity()
            result(nil)
        default:
            result(FlutterMethodNotImplemented)
        }
    }

    private func enableAppSecurity() {
        // 方式1:使用LaunchScreen.storyboard
        let splashViewController = UIStoryboard(name: "LaunchScreen", bundle: nil).instantiateInitialViewController()
        splashView = splashViewController?.view
        splashView?.frame = window!.frame
        window?.addSubview(splashView!)

        // 方式2:直接使用启动图(二选一)
        // let launchImage = UIImage(named: "LaunchImage")
        // splashView = UIImageView(image: launchImage)
        // splashView?.frame = window!.frame
        // (splashView as? UIImageView)?.contentMode = .scaleAspectFill
        // window?.addSubview(splashView!)
    }

    private func disableAppSecurity() {
        splashView?.removeFromSuperview()
        splashView = nil
    }
}

第三方包推荐

目前没有专门针对“后台显示启动页”的Flutter第三方包,自定义Method Channel实现更灵活可控,可根据应用启动页的设计自由调整UI。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:08:15