preface
Hello, everyone, it’s been a long time since I dug gold, I’m back again!! Bring you to today or a login page, but today the login page of dark and bright, like the login page white and long, night mode believes everyone not unfamiliar, iOS and android’s new version also will support pattern in the night, so this article with all of you have know simple rough night in the Flutter model how to achieve ~
The effect
Implementation approach
In fact, there is nothing magical about night mode, it is just the replacement of resources, the simplest we can set a variable isDark to determine whether it is night mode, if it is night mode, load night resources, if it is not day resources. But we need to start thinking a little bit
- How do we set a global variable
- How do we notify components to update to replace resources
Dang dang dang dang ~InheritedWidget
To help you
Let’s first think about how to tell components to update and replace resources. First of all, we can think about how to pass data between two components
class Test {
var name;
Test(this.name);
}
class A extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(child: B(test: Test('It's hard to fly')));
}
}
class B extends StatelessWidget {
final Test test;
const B({Key key, this.test}) : super(key: key);
@override
Widget build(BuildContext context) {
returnText(test.name); }}Copy the code
Easy, but ah, but this is a very simple way to pass in data that is only good for very simple logical interactions on a page, if you think about it if we have seven or eight or more components on a page, it’s like, Logical hell! The Flutter development team is obviously aware of this, so we’re going to have to use the InheritedWidget now!
InheritedWidget
What kind of duck can you make?
In short, inheritedWidgets allow for efficient propagation (and sharing) of information down the widget tree. InheritedWidget is a special Widget that is placed in the Widget tree as a parent of another child tree. All widgets of the subtree must be able to interact with the data exposed by the InheritedWidget.
For example, with the 🌰 child, we have A TodoList application with A page A list page and A page B add page
B
A
InheritedWidget
InheritedWidget
How to use
class _TodoInherited extends InheritedWidget {
_TodoInherited({Key key, @required Widget child, this.data})
: super(key: key, child: child);
final TodoState data;
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return true; }}Copy the code
Very simply, all of the InheritedWidget’s children can interact with the data exposed by the InheritedWidget because it is a tree node. Since most of our data needs to be dynamically changed when using InheritedWidget, we are bound to use StatefulWidget, So the complete code should be as follows:
class Todo {
String title;
Todo(this.title);
}
class _TodoInherited extends InheritedWidget {
_TodoInherited({Key key, @required Widget child, this.data})
: super(key: key, child: child);
final TodoState data;
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return true;
}
}
class TodoWidget extends StatefulWidget {
final Widget child;
TodoWidget({Key key, this.child}) : super(key: key);
static TodoState instanceOf(BuildContext context) {
_TodoInherited inherited = (context
.inheritFromWidgetOfExactType(_TodoInherited) as _TodoInherited);
return inherited.data;
}
@override
State<StatefulWidget> createState() => TodoState();
}
class TodoState extends State<TodoWidget> {
List<Todo> _todoList = [];
List<Todo> get todoList => _todoList;
void addTodo(String title) {
setState(() {
_todoList.add(Todo(title));
});
}
@override
Widget build(BuildContext context) {
// TODO: implement build
returnnew _TodoInherited(child: widget.child, data: this); }}Copy the code
Todo
As our data model is stored inTodoState
In the_TodoInherited
Kept inTodoState
Get reference, convenient call to getTodo
_TodoInherited
In theupdateShouldNotify
The method is used to determine whether to update and rebuildTodoWidget
In theinstanceOf
Method is used to getTodoState
Convenient access to the datainstanceOf
In thecontext.inheritFromWidgetOfExactType
Is used to register bindingsInheritedWidget
So our complete business code should look like this:
void main() {
runApp(TodoWidget(child: MyApp()));
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TodoList', debugShowCheckedModeBanner: false, home: HomePage());
}
}
class HomePage extends StatelessWidget {
Widget buildEmpty() {
return. ; } Widget buildList(List<Todo> list) {return. ; } @override Widget build(BuildContext context) { List<Todo> list = TodoWidget.instanceOf(context).todoList;return list.isEmpty ? buildEmpty() : buildList(list);
}
}
class AddTaskPage extends StatelessWidget {
final controller = TextEditingController();
void closeTask(BuildContext context) {
Navigator.pop(context);
}
Widget getTextField() {
return TextField(controller: controller);
}
@override
Widget build(BuildContext context) {
returnonTap: () { TodoWidget.instanceOf(context).addTodo(controller.text); closeTask(context); }}}Copy the code
Having said so much, night mode!!
I believe you understand the above content for the implementation of night mode should also have bamboo in mind ~ HERE I introduce an implementation method
class _CustomTheme extends InheritedWidget {
final CustomThemeState data;
_CustomTheme({this.data, Key key, @required Widget child})
: super(key: key, child: child);
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
// TODO: implement updateShouldNotify
return true;
}
}
class CustomTheme extends StatefulWidget {
final Widget child;
final MyThemeKeys initialThemeKey;
const CustomTheme({Key key, this.initialThemeKey, this.child})
: super(key: key);
@override
CustomThemeState createState() => CustomThemeState();
static ThemeModel of(BuildContext context) {
_CustomTheme inherited =
(context.inheritFromWidgetOfExactType(_CustomTheme) as _CustomTheme);
return inherited.data.theme;
}
static CustomThemeState instanceOf(BuildContext context) {
_CustomTheme inherited =
(context.inheritFromWidgetOfExactType(_CustomTheme) as _CustomTheme);
return inherited.data;
}
}
class CustomThemeState extends State<CustomTheme> {
ThemeModel _model;
ThemeModel get theme => _model;
@override
void initState() {
_model = MyThemes.getThemeFromKey(widget.initialThemeKey);
super.initState();
}
void changeTheme(MyThemeKeys themeKey) {
print(themeKey);
setState(() {
_model = MyThemes.getThemeFromKey(themeKey);
});
}
@override
Widget build(BuildContext context) {
return _CustomTheme(data: this, child: widget.child);
}
}
enum MyThemeKeys { LIGHT, DARK }
class MyThemes {
static final ThemeModel lightTheme = ThemeModel(
imageUrl: 'assets/images/banner.png', backgroundColor: Color(0xFFffFFFF), titleColor: Color(0xff3C4859), borderColor: color.black. WithOpacity (0.3), isDark:false);
static final ThemeModel darkTheme = ThemeModel(
imageUrl: 'assets/images/banner_dark.png'BackgroundColor: Color(0xff2B1C71), titleColor: Color(0xffffffff), borderColor: color.white. WithOpacity (0.3), isDark:true);
static ThemeModel getThemeFromKey(MyThemeKeys themeKey) {
switch (themeKey) {
case MyThemeKeys.LIGHT:
return lightTheme;
case MyThemeKeys.DARK:
return darkTheme;
default:
return lightTheme;
}
}
}
void main() {
runApp(CustomTheme(initialThemeKey: MyThemeKeys.LIGHT, child: MyApp()));
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false, home: HomePage()); }}Copy the code
Then we can get fonts or colors directly from ThemeModel, but there are some special situations that need special treatment, Flutter can also be handled very gracefully and conveniently, such as:
Widget build(BuildContext context) { String image = CustomTheme.of(context).imageUrl; bool isDark = CustomTheme.of(context).isDark; Widget child = isDark ? Padding(...) : Padding(...) ;return child;
}
Copy the code
Ok, so far our night mode has been implemented
Afterword.
This is still a very simple content sharing, but InheritedWidget is a very useful component that we all want to use! The landing page series continues, please stay tuned ~ 7 short of the Nuggets community’s 50 likes!!
thanks
Description of the core concepts of Flutter: Widget, State, Context, and InheritedWidget
Dynamic theming with Flutter – Flutter Community – Medium