转载: http://blog.chengyunfeng.com/?p=1041
MaterialApp代表使用纸墨设计(Material Design)风格的应用。里面包含了纸墨设计风格应用所需要的基本控件。
MaterialApp主要属性如下:
- title:在任务管理窗口中所显示的应用名字
- 主题:应用各种UI所使用的主题颜色
- color:应用的主要颜色值(primary color),也就是安卓任务管理窗口中所显示的应用颜色
- home:应用默认所显示的界面Widget
- routes:应用的顶级导航表格,这个是多页面应用用来控制页面跳转的,类似于网页的网址
- initialRoute:第一个显示的路由名字,默认值为Window.defaultRouteName
- onGenerateRoute:生成路由的回调函数,当导航的命名路由的时候,会使用这个来生成界面
- onLocaleChanged:当系统修改语言的时候,会触发å这个回调
- navigatorObservers:应用Navigator的监听器
- debugShowMaterialGrid:是否显示纸墨设计基础布局网格,用来调试UI的工具
- showPerformanceOverlay:显示性能标签,https://flutter.io/debugging/#performanceoverlay
- checkerboardRasterCacheImages,showSemanticsDebugger,debugShowCheckedModeBanner各种调试开关
Scaffold实现了基本的纸墨设计布局结构。在示例应用中,MyHomePage所返回的就是一个Scaffold。也就是说,MaterialApp的孩子是Scaffold Widget。
在纸墨设计中定义的单个界面上的各种布局元素,在Scaffold中都有支持,比如左边栏(抽屉),小吃店,以及底页。
Scaffold有下面几个主要属性:
- appBar:显示在界面顶部的一个AppBar,也就是Android中的ActionBar,工具栏
- body:当前界面所显示的主要内容Widget
- floatingActionButton:纸墨设计中所定义的FAB,界面的主要功能按钮
- persistentFooterButtons:固定在下方显示的按钮,比如对话框下方的确定,取消按钮
- 抽屉:侧边栏控件
- backgroundColor:内容的背景颜色,默认使用的是ThemeData.scaffoldBackgroundColor的值
- bottomNavigationBar:显示在页面底部的导航栏
- resizeToAvoidBottomPadding:类似于Android中的android:windowSoftInputMode =“adjustResize”,控制界面内容body是否重新布局来避免底部被覆盖了,比如当键盘显示的时候,重新布局避免被记盘盖住内容。默认值为true。
显示snackbar或者bottom sheet的时候,需要使用当前的BuildContext参数调用Scaffold.of函数来获取ScaffoldState对象,然后使用ScaffoldState.showSnackBar和ScaffoldState.showBottomSheet函数来显示。
要特别注意Scaffold.of的参数BuildContext,如果包含该BuildContext的Widget是Scaffold的父Widget,则Scaffold.of是无法查找到对应的ScaffoldState对象的,Scaffold.of返回的是父对象中最近的Scaffold中的ScaffoldState对象。比如,如果在Scaffold的构建函数中,使用构建的BuildContext参数是可以的:
1 2 3 4 5 6 7 8 9 10 11 12 | @override Widget build(BuildContext context) { return new RaisedButton( child: new Text('SHOW A SNACKBAR'), onPressed: () { Scaffold.of(context).showSnackBar(new SnackBar( content: new Text('Hello!'), )); }, ); }
|
如果构建函数返回一个Scaffold对象,则由于Scaffold对象是这个Widget的子对象,所以使用这个构建的BuildContext参数是不能查找到ScaffoldState对象的,这个时候,通过在Scaffold中使用一个Builder来提供一个新的BuildConext :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: new Text('Demo') ), body: new Builder( // Create an inner BuildContext so that the onPressed methods // can refer to the Scaffold with Scaffold.of(). builder: (BuildContext context) { return new Center( child: new RaisedButton( child: new Text('SHOW A SNACKBAR'), onPressed: () { Scaffold.of(context).showSnackBar(new SnackBar( content: new Text('Hello!'), )); }, ), ); }, ), ); } |
另外还可以把构建函数中的Widget分别创建,分别引入新的BuildContext来获取Scaffold。
AppBar和SliverAppBar是纸墨设计中的App Bar,也就是Android中的工具栏,关于工具栏的设计指南请参考纸墨设计中工具栏的内容。
AppBar和SliverAppBar都是继承至StatefulWidget类,都代表Toobar,二则的区别在于AppBar位置的固定的应用最上面的;而SliverAppBar是可以跟随内容滚动的。他们的主要属性如下:
- leading:在标题前面显示的一个控件,在首页通常显示应用的logo;在其他界面通常显示为返回按钮
- title:工具栏中主要内容,通常显示为当前界面的标题文字
- 动作:一个小工具列表,代表工具栏中所显示的菜单,对于常用的菜单,通常使用IconButton来表示;对于不常用的菜单通常使用PopupMenuButton来显示为三个点,点击后弹出二级菜单
- bottom:一个AppBarBottomWidget对象,通常是TabBar。用来在工具栏标题下面显示一个Tab导航栏
- elevation:纸墨设计中控件的z坐标顺序,默认值为4,对于可滚动的SliverAppBar,当SliverAppBar和内容同级的时候,该值为0,当内容滚动SliverAppBar变为工具栏的时候,修改elevation的值
- flexibleSpace:一个显示在AppBar下方的控件,高度和AppBar高度一样,可以实现一些特殊的效果,该属性通常在SliverAppBar中使用
- backgroundColor:APP bar的颜色,默认值为ThemeData.primaryColor。改值通常和下面的三个属性一起使用
- 亮度:App bar的亮度,有白色和黑色两种主题,默认值为ThemeData.primaryColorBrightness
- iconTheme:App栏上图标的颜色,透明度,和尺寸信息。默认值为ThemeData.primaryIconTheme
- textTheme:App bar上的文字样式。默认值为ThemeData.primaryTextTheme
- centerTitle:标题是否居中显示,默认值根据不同的操作系统,显示方式不一样
比如下面的代码在App bar上添加了功能按钮和Tabs,并指定标题居中显示,修改App bar背景颜色等:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | @override Widget build(BuildContext context) { // This method is rerun every time setState is called, for instance // as done by the _incrementCounter method above. // The Flutter framework has been optimized to make rerunning // build methods fast, so that you can just rebuild anything that // needs updating rather than having to individually change // instances of widgets. return new Scaffold( appBar: new AppBar( title: new Text(config.title), leading: new Icon(Icons.home), backgroundColor: Colors.amber[500], centerTitle: true, actions: <Widget>[ new IconButton( icon: new Icon(Icons.add_alarm), tooltip: 'Add Alarm', onPressed: () { // do nothing }), new PopupMenuButton<String>( itemBuilder: (BuildContext context) => <PopupMenuItem<String>>[ new PopupMenuItem<String>( value: "price", child: new Text('Sort by price')), new PopupMenuItem<String>( value: "time", child: new Text('Sort by time')), ], onSelected: (String action) { switch (action) { case "price": // do nothing break; case "time": // do nothing break; } }) ], bottom: new TabBar( isScrollable: true, tabs: <Widget>[ new Tab(text: "Tabs 1"), new Tab(text: "Tabs 2"), new Tab(text: "Tabs 3"), new Tab(text: "Tabs 4"), new Tab(text: "Tabs 5"), new Tab(text: "Tabs 6"), ], ), ), body: body, floatingActionButton: new FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: new Icon(Icons.add), ), // This trailing comma makes auto-formatting nicer for build methods. ); }
|
显示效果如下: