动态更改 Flutter 应用程序主题的最佳方法是什么?例如,如果用户将颜色更改为红色,我希望主题立即更改为红色。除了一个人说要使用我不熟悉的 BLOC 模式之外,我在网上找不到任何非常有用的东西。我想听听你们对这个问题的看法。谢谢!
我目前的代码结构:
var themeData = ThemeData(
fontFamily: 'Raleway',
primaryColor: Colors.blue,
brightness: Brightness.light,
backgroundColor: Colors.white,
accentColor: Colors.blue);
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: Constants.appName,
theme: themeData,
home: CheckAuth(), //CheckAuth returns MyHomePage usually
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title, @required this.uid}) : super(key: key);
final String title;
final String uid;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
...build and stuff
}
Run Code Online (Sandbox Code Playgroud)
Har*_*dia 10
如果您愿意,您可以使用InhertedWidget(而不是 BLOC) - 基本上它用于从树中的任何位置访问父小部件。
所以你应该做的是
InheritedWidget
, 在树顶的某个地方 [从你想要主题效果发生的地方]Theme
小部件上这是一些代码:
import 'package:flutter/material.dart';
var themeData = ThemeData(
fontFamily: 'Raleway',
primaryColor: Colors.blue,
brightness: Brightness.light,
backgroundColor: Colors.white,
accentColor: Colors.blue
);
void main() {
runApp(
ThemeSwitcherWidget(
initialTheme: themeData,
child: MyApp(),
),
);
}
class ThemeSwitcher extends InheritedWidget {
final _ThemeSwitcherWidgetState data;
const ThemeSwitcher({
Key key,
@required this.data,
@required Widget child,
}) : assert(child != null),
super(key: key, child: child);
static _ThemeSwitcherWidgetState of(BuildContext context) {
return (context. dependOnInheritedWidgetOfExactType(ThemeSwitcher)
as ThemeSwitcher)
.data;
}
@override
bool updateShouldNotify(ThemeSwitcher old) {
return this != old;
}
}
class ThemeSwitcherWidget extends StatefulWidget {
final ThemeData initialTheme;
final Widget child;
ThemeSwitcherWidget({Key key, this.initialTheme, this.child})
: assert(initialTheme != null),
assert(child != null),
super(key: key);
@override
_ThemeSwitcherWidgetState createState() => _ThemeSwitcherWidgetState();
}
class _ThemeSwitcherWidgetState extends State<ThemeSwitcherWidget> {
ThemeData themeData;
void switchTheme(ThemeData theme) {
setState(() {
themeData = theme;
});
}
@override
Widget build(BuildContext context) {
themeData = themeData ?? widget.initialTheme;
return ThemeSwitcher(
data: this,
child: widget.child,
);
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeSwitcher.of(context).themeData,
home: CheckAuth(),
);
}
}
Run Code Online (Sandbox Code Playgroud)
我将 ThemeSwitcherWidget 包裹在 MaterialApp 周围,因此效果贯穿整个应用程序(即使您使用 Navigator 推送新路线)。
使用ThemeSwitcher.of(context).switchTheme(themeData)
ThemeSwithcerWidget 下面的任何地方来更改主题。
在有问题的情况下,它应该调用ThemeSwitcher.of(context).switchTheme(Theme.of(context).copyWith(primaryColor: Colors.red))
在整个应用程序中将原色切换为红色,例如。在某些按钮上单击
编辑:替换inheritFromWidgetOfExactType
-> dependOnInheritedWidgetOfExactType
,因为它已被弃用 - 正如Phoca在评论中指出的那样。
使用提供程序包:
theme_changer.dart
var darkTheme = ThemeData.dark();
var lightTheme= ThemeData.light();
class ThemeChanger extends ChangeNotifier {
ThemeData _themeData;
ThemeChanger(this._themeData);
get getTheme => _themeData;
void setTheme(ThemeData theme) {
_themeData = theme;
notifyListeners();
}
}
Run Code Online (Sandbox Code Playgroud)
main.dart
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ThemeChanger(lightTheme)),
],
child: MaterialAppWithTheme(),
);
}
}
class MaterialAppWithTheme extends StatelessWidget {
@override
Widget build(BuildContext context) {
final theme = Provider.of<ThemeChanger>(context);
return MaterialApp(
theme: theme.getTheme,
home: FirstScreen(),
);
}
Run Code Online (Sandbox Code Playgroud)
first_screen.dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import './theme_changer.dart'
class FirstScreen extends StatelessWidget{
@override
Widget build(BuildContext context){
var _themeProvider=Provider.of<ThemeChanger>(context);
return Scaffold(
appBar: AppBar(title:Text("First Screen"),),
body:Container(width:MediaQuery.of(context).size.width,
height:MediaQuery.of(context).size.height,
child:Center(
child:FlatButton(child:Text("Press me"). onPressed:(){
_themeProvider.setTheme(_themeProvider.getTheme==lightTheme?darkTheme:lightTheme);
})
),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5020 次 |
最近记录: |