1 |
|
Scaffold 的创建需要传入带有 MediaQuery 数据的 Context
报错如下
1 | I/flutter ( 2928): The following assertion was thrown building TabPage(state: _TabPageState#f2fb0(ticker inactive)): |
Scaffold作为一个脚手架,创建时不能直接作为根视图,还是需要外包 MaterialApp 等,其创建后,可以为子Widget提供一些数据,比如当前 屏幕的大小,像素密度等。
我们看看 WidgetsApp 如何为下层提供MediaQuery相关数据的?
我们看到其内部使用一个MediaQueryFromWindow包裹,即从Window中获取屏幕的信息,其获取方法使用使用 WidgetsBindingObserver 的方式, 而在MediaQuery中,使用静态方法,将data绑定到Context,后续子Widget想要获取该信息就可以直接通过下面获取
1 | var data = MediaQuery.of(context) |
另外,由于MediaQuery是继承 InheritedWidget的,当子Widget实现了didChangeDependencies方法后,当屏幕信息改变,根视图WidgetsApp会 通过观察者WidgetsBindingObserver观察到,重新设置当前的MediaQueryData,之后子Widget也能收到屏幕变化,从而重建。
1 | /// Builds [MediaQuery] from `window` by listening to [WidgetsBinding]. |
1 | /// The data from the closest instance of this class that encloses the given |
///
/// If there is no [MediaQuery] in scope, then this will throw an exception.
/// To return null if there is no [MediaQuery], then pass nullOk: true
.
///
/// If you use this from a widget (e.g. in its build function), consider
/// calling [debugCheckHasMediaQuery].
static MediaQueryData of(BuildContext context, { bool nullOk = false }) {
assert(context != null);
assert(nullOk != null);
final MediaQuery query = context.dependOnInheritedWidgetOfExactType
1 |
|
在TabBar中我们就可以看大调用controller方法的例子
1 |
|
看看 _TabBarState的实现
1 |
|