第一步:安装依赖
Provider
用于管理在应用程序上实现深色主题时的状态。使用shared_preferences
来设置内存中的值,因此即使我们关闭应用程序并重新打开它,我们的数据也不会丢失
dependencies:
flutter:
sdk: flutter
provider: ^6.0.4
shared_preferences: ^2.0.15
第二步:创建一个类SharedPreferences
创建了一个类DarkThemePreference,我们在其中存储深色主题的值,写了两个方法分别来保存和获得值。
import 'package:shared_preferences/shared_preferences.dart';
class DarkThemePreference {
static const THEME_STATUS = "THEMESTATUS";
setDarkTheme(bool value) async{
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setBool(THEME_STATUS, value);
}
Future<bool> getTheme() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getBool(THEME_STATUS) ?? false;
}
}
第三步:创建模型
import 'package:flutter/material.dart';
import 'package:flutter_base/model/DarkThemePreference.dart';
class DarkThemeProvider with ChangeNotifier{
DarkThemePreference darkThemePreference = DarkThemePreference();
bool _darkTheme = false;
bool get darkTheme => _darkTheme;
set darkTheme(bool value){
_darkTheme = value;
darkThemePreference.setDarkTheme(value);
notifyListeners();
}
}
第四步:设置暗黑样式
//dark_theme_styles.dart
import 'dart:ui';
import 'package:flutter/material.dart';
class Styles {
static ThemeData themeData(bool isDarkTheme, BuildContext context) {
return ThemeData(
primarySwatch: Colors.blue,
primaryColor: isDarkTheme ? Colors.black : Colors.white,
backgroundColor: isDarkTheme ? Colors.black : const Color(0xffF1F5FB),
indicatorColor: isDarkTheme ? const Color(0xff0E1D36) : const Color(0xffCBDCF8),
hintColor: isDarkTheme ? const Color(0xff280C0B) : const Color(0xffEECED3),
highlightColor: isDarkTheme ? const Color(0xff372901) :const Color(0xffFCE192),
hoverColor: isDarkTheme ? const Color(0xff3A3A3B) : const Color(0xff4285F4),
focusColor: isDarkTheme ? const Color(0xff0B2512) : const Color(0xffA8DAB5),
disabledColor: Colors.grey,
cardColor: isDarkTheme ? const Color(0xFF151515) : Colors.white,
canvasColor: isDarkTheme ? Colors.black : Colors.grey[50],
brightness: isDarkTheme ? Brightness.dark : Brightness.light,
elevatedButtonTheme: ElevatedButtonThemeData(
style: ButtonStyle(
backgroundColor:isDarkTheme? MaterialStateProperty.all<Color>(Colors.blueGrey,) : MaterialStateProperty.all<Color>(const Color(0xff4285F4)), //button color
foregroundColor: MaterialStateProperty.all<Color>(Colors.white), //text (and icon)
),
),
buttonTheme: Theme.of(context).buttonTheme.copyWith(
colorScheme: isDarkTheme ? const ColorScheme.dark() :const ColorScheme.light()),
appBarTheme:const AppBarTheme(
elevation: 0.0,
), textSelectionTheme: TextSelectionThemeData(selectionColor: isDarkTheme ? Colors.white : Colors.black),
);
}
}
第五步:将Provider加入MaterialApp
class _MyAppState extends State<MyApp> {
DarkThemeProvider themeChangeProvider = DarkThemeProvider();
@override
void initState() {
// TODO: implement initState
getCurrentAppTheme();
super.initState();
}
void getCurrentAppTheme() async{
themeChangeProvider.darkTheme = await themeChangeProvider.darkThemePreference.getTheme();
}
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context)=>themeChangeProvider)
],
child: Consumer<DarkThemeProvider>(
builder: (context,darkModeProvider,child){
return MaterialApp(
title: 'Flutter Demo',
theme: Styles.themeData(themeChangeProvider.darkTheme, context),
initialRoute: '/',//名为"/"的路由作为应用的home(首页)
//注册路由
routes: {
'/':(context)=> MyHomePage(title: '样式实例入口'),//注册首页路由
},
);
},
),
);
}
}
第六步:编写一个开关按钮
final themeProvider = Provider.of<DarkThemeProvider>(context);
//...省略代码...
Positioned(
right:0,
top: 0,
child: GestureDetector(
onTap: (){
themeProvider.darkTheme = !themeProvider.darkTheme;
},
child: Container(
height:150,
width: 50,
decoration: BoxDecoration(
borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(30),
bottomRight: Radius.circular(30)
),
shape: BoxShape.rectangle,
color: Theme.of(context).hoverColor,
),
child: Padding(
padding: const EdgeInsets.only(left: 12,right: 12,bottom: 28),
child:themeProvider.darkTheme
? Image.asset('images/bulb_off.png',fit: BoxFit.fitHeight,)
: Image.asset('images/bulb_on.png',fit: BoxFit.fitHeight,)
),
),
)
),