当前位置: 首页 > news >正文

Flutter与原生混合开发:实现完美的暗夜模式同步方案

在 Flutter 与原生混合开发中保证暗夜模式一致性,需要从 Flutter 端和原生端(Android/iOS)同时进行配置和同步。以下是完整的解决方案:

  1. Flutter 端配置

1.1 使用 Provider 状态管理(推荐)

// theme_provider.dart
import 'package:flutter/material.dart';class ThemeProvider with ChangeNotifier {ThemeMode _themeMode = ThemeMode.system;ThemeMode get themeMode => _themeMode;bool get isDarkMode => _themeMode == ThemeMode.dark;void setThemeMode(ThemeMode mode) {_themeMode = mode;notifyListeners();}void toggleTheme() {_themeMode = _themeMode == ThemeMode.light ? ThemeMode.dark : ThemeMode.light;notifyListeners();}
}

1.2 MaterialApp 配置

void main() {runApp(ChangeNotifierProvider(create: (context) => ThemeProvider(),child: const MyApp(),),);
}class MyApp extends StatelessWidget {const MyApp({super.key});Widget build(BuildContext context) {return Consumer<ThemeProvider>(builder: (context, themeProvider, child) {return MaterialApp(theme: ThemeData.light().copyWith(// 自定义亮色主题primaryColor: Colors.blue,scaffoldBackgroundColor: Colors.white,),darkTheme: ThemeData.dark().copyWith(// 自定义暗色主题primaryColor: Colors.blue[700],scaffoldBackgroundColor: Colors.grey[900],),themeMode: themeProvider.themeMode,home: const HomePage(),);},);}
}
  1. Android 端配置

2.1 在 MainActivity 中同步主题

// MainActivity.kt
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannelclass MainActivity: FlutterActivity() {private val CHANNEL = "theme_channel"override fun configureFlutterEngine(flutterEngine: FlutterEngine) {super.configureFlutterEngine(flutterEngine)MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL).setMethodCallHandler {call, result ->when (call.method) {"getSystemTheme" -> {val nightMode = resources.configuration.uiMode and android.content.res.Configuration.UI_MODE_NIGHT_MASKval isDark = nightMode == android.content.res.Configuration.UI_MODE_NIGHT_YESresult.success(isDark)}"setAppTheme" -> {val isDark = call.arguments as BooleansetAppTheme(isDark)result.success(null)}else -> result.notImplemented()}}}private fun setAppTheme(isDark: Boolean) {// 设置原生端主题if (isDark) {// 应用暗色主题setTheme(android.R.style.Theme_DeviceDefault_Dark)} else {// 应用亮色主题setTheme(android.R.style.Theme_DeviceDefault_Light)}recreate() // 重新创建Activity应用主题}
}

2.2 AndroidManifest.xml 配置

<applicationandroid:name=".MainApplication"android:theme="@style/LaunchTheme"><activityandroid:name=".MainActivity"android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"android:hardwareAccelerated="true"android:theme="@style/NormalTheme"><!-- 其他配置 --></activity>
</application>
  1. iOS 端配置

3.1 在 AppDelegate 中同步主题

// AppDelegate.swift
import UIKit
import Flutter@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {let CHANNEL = "theme_channel"override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {let controller : FlutterViewController = window?.rootViewController as! FlutterViewControllerlet channel = FlutterMethodChannel(name: CHANNEL, binaryMessenger: controller.binaryMessenger)channel.setMethodCallHandler({[weak self] (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void inswitch call.method {case "getSystemTheme":self?.getSystemTheme(result: result)case "setAppTheme":if let arguments = call.arguments as? [String: Any],let isDark = arguments["isDark"] as? Bool {self?.setAppTheme(isDark: isDark)result(nil)} else {result(FlutterError(code: "INVALID_ARGUMENT", message: "Invalid arguments", details: nil))}default:result(FlutterMethodNotImplemented)}})GeneratedPluginRegistrant.register(with: self)return super.application(application, didFinishLaunchingWithOptions: launchOptions)}private func getSystemTheme(result: FlutterResult) {if #available(iOS 13.0, *) {let isDark = UITraitCollection.current.userInterfaceStyle == .darkresult(isDark)} else {result(false) // iOS 13以下默认亮色}}private func setAppTheme(isDark: Bool) {// 设置原生端主题if #available(iOS 13.0, *) {window?.overrideUserInterfaceStyle = isDark ? .dark : .light}}
}
  1. Flutter 与原生通信

4.1 创建通信工具类

// native_theme_handler.dart
import 'package:flutter/services.dart';class NativeThemeHandler {static const MethodChannel _channel = MethodChannel('theme_channel');// 获取系统主题static Future<bool> getSystemTheme() async {try {final bool isDark = await _channel.invokeMethod('getSystemTheme');return isDark;} on PlatformException {return false;}}// 设置原生端主题static Future<void> setNativeTheme(bool isDark) async {try {await _channel.invokeMethod('setAppTheme', {'isDark': isDark});} on PlatformException catch (e) {print('Failed to set native theme: ${e.message}');}}
}

4.2 在主题提供者中同步

// 修改 theme_provider.dart
class ThemeProvider with ChangeNotifier {// ... 其他代码Future<void> syncWithSystem() async {final bool isSystemDark = await NativeThemeHandler.getSystemTheme();_themeMode = isSystemDark ? ThemeMode.dark : ThemeMode.light;await NativeThemeHandler.setNativeTheme(isSystemDark);notifyListeners();}Future<void> setThemeAndSync(ThemeMode mode) async {_themeMode = mode;await NativeThemeHandler.setNativeTheme(mode == ThemeMode.dark);notifyListeners();}
}
  1. 监听系统主题变化

5.1 Flutter 端监听

// 在 main.dart 或首页中添加
class HomePage extends StatefulWidget {const HomePage({super.key});State<HomePage> createState() => _HomePageState();
}class _HomePageState extends State<HomePage> with WidgetsBindingObserver {void initState() {super.initState();WidgetsBinding.instance.addObserver(this);_initTheme();}void dispose() {WidgetsBinding.instance.removeObserver(this);super.dispose();}void didChangePlatformBrightness() {// 系统亮度变化时同步context.read<ThemeProvider>().syncWithSystem();super.didChangePlatformBrightness();}void _initTheme() async {// 初始化时同步主题await context.read<ThemeProvider>().syncWithSystem();}Widget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('主题演示'),actions: [IconButton(icon: const Icon(Icons.brightness_6),onPressed: () {context.read<ThemeProvider>().toggleTheme();NativeThemeHandler.setNativeTheme(context.read<ThemeProvider>().isDarkMode);},),],),body: const Center(child: Text('主题同步示例'),),);}
}
  1. 持久化存储
// 使用 shared_preferences 保存主题偏好
import 'package:shared_preferences/shared_preferences.dart';class ThemeProvider with ChangeNotifier {// ... 其他代码Future<void> loadTheme() async {final prefs = await SharedPreferences.getInstance();final themeIndex = prefs.getInt('themeMode') ?? ThemeMode.system.index;_themeMode = ThemeMode.values[themeIndex];// 如果是系统模式,同步系统主题if (_themeMode == ThemeMode.system) {await syncWithSystem();} else {await NativeThemeHandler.setNativeTheme(_themeMode == ThemeMode.dark);}notifyListeners();}Future<void> saveTheme() async {final prefs = await SharedPreferences.getInstance();await prefs.setInt('themeMode', _themeMode.index);}Future<void> setThemeAndSync(ThemeMode mode) async {_themeMode = mode;await NativeThemeHandler.setNativeTheme(mode == ThemeMode.dark);await saveTheme();notifyListeners();}
}
  1. 使用注意事项

  2. 初始化顺序:在应用启动时先加载保存的主题设置

  3. 错误处理:妥善处理平台通信可能出现的异常

  4. 性能考虑:避免频繁的主题切换操作

  5. 测试:分别在亮色和暗色模式下测试所有界面

这样配置后,你的 Flutter 与原生混合应用就能在各个平台上保持暗夜模式的一致性了。


文章转载自:

http://0CRRI1Ni.fnwny.cn
http://N8AmmEvh.fnwny.cn
http://w9VEYTJQ.fnwny.cn
http://NREW4sAv.fnwny.cn
http://qqMlK9m3.fnwny.cn
http://o8Wu7lVE.fnwny.cn
http://RG8XCMSO.fnwny.cn
http://QcBbRvqE.fnwny.cn
http://27hNIFQb.fnwny.cn
http://ImYHcZtg.fnwny.cn
http://0KSwnOBL.fnwny.cn
http://xxcijM3d.fnwny.cn
http://EY532iK3.fnwny.cn
http://31HxOeIn.fnwny.cn
http://swEQ9GSO.fnwny.cn
http://KTVMOCtk.fnwny.cn
http://FFK2fkex.fnwny.cn
http://93bHZ5lp.fnwny.cn
http://GHQMz7Ik.fnwny.cn
http://5WEHGVZJ.fnwny.cn
http://pFjZgKaB.fnwny.cn
http://ZfwHLF8u.fnwny.cn
http://OUqweo8u.fnwny.cn
http://r1mF9MIj.fnwny.cn
http://1Rm6iAeu.fnwny.cn
http://OdmPe4BB.fnwny.cn
http://HsXv55pq.fnwny.cn
http://GiL9coK6.fnwny.cn
http://tVAAV7NS.fnwny.cn
http://RQhZWTXd.fnwny.cn
http://www.dtcms.com/a/378622.html

相关文章:

  • AT_abc422_f [ABC422F] Eat and Ride 题解
  • 面试问题详解十八:QT中自定义控件的三种实现方式
  • sql 中的 over() 窗口函数
  • Nginx优化与 SSL/TLS配置
  • Git远程操作(三)
  • 深入解析Spring AOP核心原理
  • 虫情测报仪:通过自动化、智能化的手段实现害虫的实时监测与预警
  • Python快速入门专业版(二十二):if语句进阶:嵌套if与条件表达式(简洁写法技巧)
  • 研发文档分类混乱如何快速查找所需内容
  • Java Web实现“十天内免登录”功能
  • CH347使用笔记:CH347在Vivado下的使用教程
  • 【linux内存管理】【基础知识 1】【pgd,p4d,pud,pmd,pte,pfn,pg,ofs,PTRS概念介绍】
  • 详解mcp以及agent java应用架构设计与实现
  • 硬件开发2-ARM裸机开发2-IMX6ULL
  • 电商网站被DDoS攻击了怎么办?
  • Java NIO的底层原理
  • QT 常用控件(概述、QWidget核心属性、按钮类控件、显示类控件、输入类控件、多元素控件、容器类控件、布局管理器)
  • MATLAB2-结构化编程和自定义函数-台大郭彦甫视频
  • 鸿蒙的编程软件的介绍
  • 鸿蒙审核问题——Scroll中嵌套了List/Grid时滑动问题
  • REDPlayer 鸿蒙原生视频播放库组件介绍与使用指南
  • HarmonyOS 应用开发深度解析:ArkUI 声明式 UI 与现代化状态管理最佳实践
  • redis 入门-1
  • Json-rpc通信项目(基于C++ Jsoncpp muduo库)
  • TODO的面试(dw三面、sqb二面、ks二面)
  • Vibe Coding实战项目:用Qwen3-Coder做了个AI跳舞视频生成器
  • Vue 封装Input组件 双向通信
  • 【混合开发】进阶到【大前端++】
  • ZooKeeper Java客户端与分布式应用实战
  • 【复习】计网每日一题---传输层无连接不可靠服务