InheritedWidget
是一个具有特殊功能的组件,它提供可以将资料从 widget
从上到下传递的功能,达到共享数据的目的,其重要性与 StatelessWidget
和 StatefulWidget
相当。
我们在MaterialApp
可以使用ThemeData
定义App整体的风格,
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
theme: ThemeData(
primaryColor: Colors.green,
accentColor: Colors.yellow[300],
textTheme: const TextTheme(
headline6: TextStyle(fontSize: 24.0, fontStyle: FontStyle.italic),
),
),
initialRoute: '/',
routes: {
'/': (context) => HomeScreen(),
'/theme': (context) => ThemeScreen(),
},
);
}
}
在底层的 widget 可以使用 Theme.of(context)
的方法取得上层的共享资料
class ThemeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text("Button")),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Theme.of(context).accentColor,
child: Text(
'使用来自 MaterialApp 设定的 ThemeData',
style: Theme.of(context).textTheme.headline6,
),
),
],
),
);
}
}
Flutter 习惯使用名称为 of
的静态方法,定义 InheritedWidget
功能组件的使用,其应用 BuildContext
的dependOnInheritedWidgetOfExactType
方法从 Element Tree 向父层寻找符合 MyThemeWidget
型态的资源。
让我们使用 InheritedWidget 实作 MyThemeWidget
,共享自己定义的 MyThemeData
样式资料。
class MyThemeData {
final Color? primaryColor;
MyThemeData({this.primaryColor});
MyThemeData.fallback() : this(primaryColor: Colors.blue);
}
class MyThemeWidget extends InheritedWidget {
final MyThemeData? data;
MyThemeWidget({required Widget child, this.data}) : super(child: child);
@override
bool updateShouldNotify(MyThemeWidget oldWidget) {
return oldWidget.data != data;
}
static MyThemeData of(BuildContext context) {
final MyThemeWidget? _inheritedTheme =
context.dependOnInheritedWidgetOfExactType<MyThemeWidget>();
MyThemeData theme = _inheritedTheme?.data ?? MyThemeData.fallback();
return theme;
}
}
范例中我们使用 Switch 模拟 MyThemeData 资料变更的状况
class MyThemeBox extends StatefulWidget {
_MyThemeBoxState createState() => _MyThemeBoxState();
}
class _MyThemeBoxState extends State<MyThemeBox> {
bool toggle = false;
Widget build(BuildContext context) {
var color;
if (toggle) {
color = Colors.red;
} else {
color = Colors.blue;
}
return MyThemeWidget(
data: MyThemeData(primaryColor: color),
child: Container(
child: Column(
children: [
Switch(
value: toggle,
onChanged: (bool value) {
setState(() {
toggle = value;
});
},
),
TextLabel(),
],
),
),
);
}
}
这边是我们在 MyThemeWidget 底层的组件,可通过of
取得 MyThemeData 资料。
还记得当初在谈 State 生命周期的时候有提到 didChangeDependencies
的触发与是否有使用 InheritedWidget
内的资料有关。
class TextLabel extends StatefulWidget {
_TextLabelState createState() => _TextLabelState();
}
class _TextLabelState extends State<TextLabel> {
@override
void didChangeDependencies() {
super.didChangeDependencies();
print("didChangeDependencies()");
}
@override
Widget build(BuildContext context) {
var primaryColor = MyThemeWidget.of(context).primaryColor;
return Text(
"使用来自 MyThemeWidget 设定的 MyThemeData",
style: TextStyle(color: primaryColor),
);
}
}
<<: day 19 - health check 让k8s帮忙关怀服务
今天主要要来介绍这三个元件及彼此之间一个简单的应用,首先先来提一下EditText、textView...
再熟悉不过的字串,也算是资料结构? 我们常常使用的字串,也算是一种有顺序关系的「序列容器」,因此...
今天就废话不多说把注册页写完吧! 注册页 一样先来构思画面,由上而下AppBar,标题,描述文字,e...
这篇开始使用 Tag Helper 来 Render 出需要的 Html 控制项 name,方便在 ...
前言 这篇,想要介绍一下 Flutter 如何把某些功能打包给原生的 Android、Ios 写。将...