如何在运行时根据应用主题切换启动屏?
iOS端实现跟随应用内主题切换启动屏(Flutter适配)
因为启动屏是iOS系统在Flutter引擎加载前就渲染的,所以无法直接通过Flutter控制,必须借助iOS原生代码实现,核心思路是用临时视图模拟启动屏,根据应用内预存的主题设置动态加载对应样式,待Flutter加载完成后再切换到Flutter页面。
具体实现步骤
1. 准备两套启动屏资源
在Xcode中创建两个Launch Screen Storyboard:
LaunchScreenLight.storyboard:配置浅色主题的启动屏(白色背景等)LaunchScreenDark.storyboard:配置深色主题的启动屏(黑色背景等)
确保两个storyboard的布局结构完全一致,仅颜色等主题相关元素不同。
2. 同步Flutter主题设置到iOS原生存储
当用户在Flutter内切换主题时,通过MethodChannel将主题值同步到iOS的UserDefaults中:
Flutter端代码
import 'package:flutter/services.dart'; class ThemeSync { static const _channel = MethodChannel('app/theme_sync'); /// 保存当前选中的主题到原生存储 static Future<void> saveSelectedTheme(String theme) async { await _channel.invokeMethod('saveTheme', {'theme': theme}); } }
iOS端代码(AppDelegate.swift)
import UIKit import Flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // 初始化MethodChannel处理主题同步 let themeChannel = FlutterMethodChannel(name: "app/theme_sync", binaryMessenger: window?.rootViewController as! FlutterViewController) themeChannel.setMethodCallHandler { (call, result) in guard call.method == "saveTheme", let args = call.arguments as? [String: String], let theme = args["theme"] else { result(FlutterError(code: "INVALID_ARGS", message: "参数无效", details: nil)) return } UserDefaults.standard.set(theme, forKey: "selected_app_theme") result(nil) } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } }
3. 动态加载对应主题的启动屏
修改AppDelegate.swift,在Flutter引擎启动前先加载对应主题的临时启动屏,待Flutter就绪后再切换:
override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { // 读取预存的主题,默认浅色 let savedTheme = UserDefaults.standard.string(forKey: "selected_app_theme") ?? "light" let launchStoryboardName = savedTheme == "dark" ? "LaunchScreenDark" : "LaunchScreenLight" // 加载对应主题的启动屏视图控制器 let launchStoryboard = UIStoryboard(name: launchStoryboardName, bundle: nil) let launchVC = launchStoryboard.instantiateInitialViewController()! // 设置临时启动屏为当前根控制器 window?.rootViewController = launchVC window?.makeKeyAndVisible() // 初始化Flutter引擎 let flutterEngine = FlutterEngine(name: "AppFlutterEngine") flutterEngine.run() GeneratedPluginRegistrant.register(with: flutterEngine) // 延迟切换到Flutter页面(确保启动屏显示足够时间,避免闪屏) DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { [weak self] in let flutterVC = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil) self?.window?.rootViewController = flutterVC } // 主题同步的MethodChannel逻辑(保留之前的代码) let themeChannel = FlutterMethodChannel(name: "app/theme_sync", binaryMessenger: flutterEngine.binaryMessenger) themeChannel.setMethodCallHandler { (call, result) in guard call.method == "saveTheme", let args = call.arguments as? [String: String], let theme = args["theme"] else { result(FlutterError(code: "INVALID_ARGS", message: "参数无效", details: nil)) return } UserDefaults.standard.set(theme, forKey: "selected_app_theme") result(nil) } return true }
注意事项
- 两套启动屏的布局必须完全一致,否则切换到Flutter页面时会出现视觉跳变。
- 首次启动时
UserDefaults无主题记录,默认使用浅色主题,可根据需求修改默认值。 - 延迟切换的时间可根据实际情况调整,确保Flutter引擎完全加载,避免闪屏。
内容的提问来源于stack exchange,提问作者iSuu273
相关产品推荐
相关产品推荐

