Flutter的主题更换方式,是我所预料不到的。
Flutter更换主题,可以统一更换。
Flutter UI与原生的Android APP不同,Flutter UI默认就是Material Design 风格,而原生的Android APP有多种UI,开发者开发过程中如果不小心使用不同UI框架的UI,在修改主题这一需求的道路上便会难走许多。
开始
使用到的第三方库:
shared_preferences: ^2.0.7 # 本地存储 -- 实现主题持久化
provider: ^6.0.1 # 对InheritedWidget进行包装,使其更易于使用和重用。
shared_preferences :类似原生Android开发的SharedPreferences ,作用都是本地存储,用法也基本一致,只是Flutter的shared_preferences 需要通过异步关键字async 才能调用。具体可见:shared_preferences provider :goole官方推荐的状态管理器,具体可见:provider
主题设置
在主题设置开始之前,需要先写一个with ChangeNotifier 的dart 文件,我们需要使用ChangeNotifier 通知页面的主题已发生变化,需要去更新界面
class AppTheme with ChangeNotifier {
ThemeData theme;
static String black = "black",
blue = "blue",
red = "red",
yellow = "yellow",
white = "white";
setTheme(String themeStr) {
if (themeStr != "" && themeStr != null) {
if (themeStr == black) {
theme = themeBlack;
} else if (themeStr == blue) {
theme = themeBlue;
} else if (themeStr == red) {
theme = themeRed;
} else if (themeStr == yellow) {
theme = themeYellow;
} else if (themeStr == white) {
theme = themeWhite;
}
} else {
theme = themeWhite;
}
notifyListeners();
}
getTheme() {
return theme == null ? themeWhite : theme;
}
}
在需要修改主题的界面加上
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [ChangeNotifierProvider(create: (_) => AppTheme())],
child: Consumer<AppTheme>(builder: (context, appTheme, _) {
return MaterialAppTheme();
}));
}
代码中的MaterialApp() 即是自己编写的界面样式,MaterialApp 提供了theme 属性,这一属性,便是控制整个APP主题样式的地方。
Widget MaterialAppTheme() {
return MaterialApp(
title: 'First Flutter Project',
theme: 设置的主题,
home: Scaffold(
appBar: AppBar(
title: Text("首页"),
),
body: Container(
child: ListView.builder(
itemCount: item.length,
itemBuilder: (context, index) {
String text = item[index]["text"];
return InkWell(
onTap: () {
clickListItem(context, index);
},
child: ListTile(
title: Text(
text,
),
trailing: Icon(Icons.chevron_right),
),
);
},
),
),
),
);
}
void clickListItem(BuildContext context, int index) {
if (index == 0) {
showSystemThemeDialog(context);
} else if (index == 1) {
showCustomThemeDialog(context);
} else if (index == 2) {
Navigator.push(
context, MaterialPageRoute(builder: (context) => NewPage()));
}
}
点击列表之时,弹出一个框选择主题的颜色。
void showSystemThemeDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return SimpleDialog(
title: Text("选择自定义主题"),
children: [
SimpleDialogOption(
child: Container(
child: Text(""),
color: Colors.blue,
height: SimpleDialogOptionHeight,
),
onPressed: () => selectTheme(context, AppTheme.blue),
),
SimpleDialogOption(
child: Container(
child: Text(""),
color: Colors.red,
height: SimpleDialogOptionHeight,
),
onPressed: () => selectTheme(context, AppTheme.red),
),
SimpleDialogOption(
child: Container(
child: Text(""),
color: Colors.yellow,
height: SimpleDialogOptionHeight,
),
onPressed: () => selectTheme(context, AppTheme.yellow),
),
],
);
},
);
}
void showCustomThemeDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) {
return SimpleDialog(
title: Text("选择系统主题"),
children: [
SimpleDialogOption(
child: Container(
child: Text(""),
color: Colors.white,
height: SimpleDialogOptionHeight,
),
onPressed: () => selectTheme(context, AppTheme.white),
),
SimpleDialogOption(
child: Container(
child: Text(""),
color: Colors.black,
height: SimpleDialogOptionHeight,
),
onPressed: () => selectTheme(context, AppTheme.black),
),
],
);
},
);
}
系统主题
在Flutter中,有两种皮肤,即Brightness.dark 与Brightness.light ,我们所看到的默认使用的是Brightness.light ,如果想换成Brightness.dark 风格,在MaterialApp 的theme 设置ThemeData(brightness: Brightness.dark) 即可
自定义主题
自定义的主题设置起来比较麻烦,要设置的theme 属性,真滴是太多啦,点击查看自定义属性
主题持久化
主题持久化的实现,依靠的是shared_preferences 第三方库,在每次更换主题时修改掉本地储存的样式,启动APP再在渲染界面完成前取得上次APP关闭的颜色就好了
打开APP时提前设置主题theme
SharedPreferencesUtil.instance
.getString("theme")
.then((value) => {this.appTheme.setTheme(value)});
在渲染MaterialApp 前,得到提前预设的主题,放上去就好
theme: this.appTheme.getTheme(),
ThemeData参数
factory ThemeData({
Brightness brightness,
MaterialColor primarySwatch,
Color primaryColor,
Brightness primaryColorBrightness,
Color primaryColorLight,
Color primaryColorDark,
Color accentColor,
Brightness accentColorBrightness,
Color canvasColor,
Color scaffoldBackgroundColor,
Color bottomAppBarColor,
Color cardColor,
Color dividerColor,
Color highlightColor,
Color splashColor,
InteractiveInkFeatureFactory splashFactory,
Color selectedRowColor,
Color unselectedWidgetColor,
Color disabledColor,
Color buttonColor,
ButtonThemeData buttonTheme,
Color secondaryHeaderColor,
Color textSelectionColor,
Color cursorColor,
Color textSelectionHandleColor,
Color backgroundColor,
Color dialogBackgroundColor,
Color indicatorColor,
Color hintColor,
Color errorColor,
Color toggleableActiveColor,
String fontFamily,
TextTheme textTheme,
TextTheme primaryTextTheme,
TextTheme accentTextTheme,
InputDecorationTheme inputDecorationTheme,
IconThemeData iconTheme,
IconThemeData primaryIconTheme,
IconThemeData accentIconTheme,
SliderThemeData sliderTheme,
TabBarTheme tabBarTheme,
CardTheme cardTheme,
ChipThemeData chipTheme,
TargetPlatform platform,
MaterialTapTargetSize materialTapTargetSize,
PageTransitionsTheme pageTransitionsTheme,
AppBarTheme appBarTheme,
BottomAppBarTheme bottomAppBarTheme,
ColorScheme colorScheme,
DialogTheme dialogTheme,
Typography typography,
CupertinoThemeData cupertinoOverrideTheme
})
避坑指南: 1、热刷新无法更换修改后刷新的样式,往往都需要卸载APP,然后重新安装才能展示出效果 2、自定义appBarTheme,自定义的样式会覆盖掉原有的全部样式
本文代码链接:点击下载
|