一,前言:
MaterialApp和Scaffold是Flutter提供的兩個Widget,其中:
- MaterialApp是一個方便的Widget,它封裝了應用程序實現Material Design所需要的一些Widget。
- Scaffold組件是Material Design布局結構的基本實現。此類提供了用於顯示drawer、snackbar和底部sheet的API。MaterialApp 的 child 是 Scaffold Widget。
二,MaterialApp屬性介紹
* 22個參數
| 字段 | 類型 |
|---|---|
| navigatorKey(導航鍵) | GlobalKey<NavigatorState> |
| home(主頁) | Widget |
| routes(路由) | Map<String, WidgetBuilder> |
| initialRoute(初始路由) | String |
| onGenerateRoute(生成路由) | RouteFactory |
| onUnknownRoute(未知路由) | RouteFactory |
| navigatorObservers(導航觀察器) | List<NavigatorObserver> |
| builder(建造者) | TransitionBuilder |
| title(標題) | String |
| onGenerateTitle(生成標題) | GenerateAppTitle |
| color(顏色) | Color |
| theme(主題) | ThemeData |
| locale(地點) | Locale |
| localizationsDelegates(本地化委托) | Iterable<LocalizationsDelegate<dynamic>> |
| localeResolutionCallback(區域分辨回調) | LocaleResolutionCallback |
| supportedLocales(支持區域) | Iterable<Locale> |
| debugShowMaterialGrid(調試顯示材質網格) | bool |
| showPerformanceOverlay(顯示性能疊加) | bool |
| checkerboardRasterCacheImages(棋盤格光柵緩存圖像) | bool |
| checkerboardOffscreenLayers(棋盤格層) | bool |
| showSemanticsDebugger(顯示語義調試器) | bool |
| debugShowCheckedModeBanner(調試顯示檢查模式橫幅) | bool |
1. navigatorKey
navigatorKey.currentState
相當於
Navigator.of(context)
使用
GlobalKey<NavigatorState> _navigatorKey=new GlobalKey(); new MaterialApp( navigatorKey: _navigatorKey, );
2. home
進入程序后顯示的第一個頁面,傳入的是一個Widget,但實際上這個Widget需要包裹一個Scaffold以顯示該程序使用Material Design風格
注意:這個是一個 Widget 對象,用來定義當前應用打開的時候,所顯示的界面。
使用
class MyApp extends StatelessWidget { // This widget is the root of your application. @override Widget build(BuildContext context) { return new MaterialApp( home: new MyHomePage(), ); } }
//這是一個可改變的Widget class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() => new _MyHomePageState(); }
class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return new Scaffold( appBar: new AppBar( title: Text('Title'), ), body: Center( child: Text('Home'), ), ); } }
3. routes
聲明程序中有哪個通過Navigation.of(context).pushNamed跳轉的路由
參數以鍵值對的形式傳遞
key:路由名字
value:對應的Widget
注意:
定義應用中頁面跳轉規則。 該對象是一個 Map<String, WidgetBuilder>。當使用 Navigator.pushNamed 來路由的時候,會在 routes 查找路由名字,然后使用 對應的 WidgetBuilder 來構造一個帶有頁面切換動畫的 MaterialPageRoute。如果應用只有一個界面,則不用設置這個屬性,使用 home 設置這個界面即可。如果 home 不為 null,當 routes 中包含 Navigator.defaultRouteName('/') 的時候會出錯,兩個都是 home 沖突了。如果所查找的路由在 routes 中不存在,則會通過 onGenerateRoute 來查找。
使用
new MaterialApp( routes: { '/home':(BuildContext context) => HomePage(), '/home/one':(BuildContext context) => OnePage(), //.... }, );
4 . initialRoute
初始路由,當用戶進入程序時,自動打開對應的路由。
(home還是位於一級)
傳入的是上面routes的key
跳轉的是對應的Widget(如果該Widget有Scaffold.AppBar,並不做任何修改,左上角有返回鍵)
注意:用指定默認顯示的路由名字,默認值為 Window.defaultRouteName
使用
new MaterialApp( routes: { '/home':(BuildContext context) => HomePage(), '/home/one':(BuildContext context) => OnePage(), //.... }, initialRoute: '/home/one', );
5 . onGenerateRoute
當通過Navigation.of(context).pushNamed跳轉路由時,
在routes查找不到時,會調用該方法
使用
new MaterialApp( routes: { '/home':(BuildContext context) => HomePage(), '/home/one':(BuildContext context) => OnePage(), //.... }, onGenerateRoute: (setting){ //setting.isInitialRoute; bool類型 是否初始路由 //setting.name; 要跳轉的路由名key return new PageRouteBuilder( pageBuilder: (BuildContext context, _, __) { //這里為返回的Widget return HomePage(); }, opaque: false, //跳轉動畫 transitionDuration: new Duration(milliseconds: 200), transitionsBuilder: (___, Animation<double> animation, ____, Widget child) { return new FadeTransition( opacity: animation, child: new ScaleTransition( scale: new Tween<double>(begin: 0.5, end: 1.0) .animate(animation), child: child, ), ); }); } );
6 . onUnknownRoute
效果跟onGenerateRoute一樣
調用順序為onGenerateRoute ==> onUnknownRoute
7 . navigatorObservers
路由觀察器,當調用Navigator的相關方法時,會回調相關的操作
使用
new MaterialApp( navigatorObservers: [ MyObserver(), ], ); //繼承NavigatorObserver class MyObserver extends NavigatorObserver{ @override void didPush(Route route, Route previousRoute) { // 當調用Navigator.push時回調 super.didPush(route, previousRoute); //可通過route.settings獲取路由相關內容 //route.currentResult獲取返回內容 //....等等 print(route.settings.name); } }
8 . builder
當構建一個Widget前調用
一般做字體大小,方向,主題顏色等配置
使用
new MaterialApp( builder: (BuildContext context, Widget child) { return MediaQuery( data: MediaQuery.of(context).copyWith( //字體大小 textScaleFactor: 1.4, ), child: child, ); }, );
9 . title
該標題出現在
Android:任務管理器的程序快照之上
IOS: 程序切換管理器中
注意:這個和啟動圖標名字是不一樣的,和當前 Activity 的名字也是不一樣的。 這個 Title 是用來定義任務管理窗口界面所看到應用名字的。在原生 Android 系統中點擊圓圈 Home 按鈕右邊的方塊按鈕就會打開多任務切換窗口。
使用
new MaterialApp( title: 'Flutter應用', );
10 . onGenerateTitle
跟上面的tiitle一樣,但含有一個context參數
用於做本地化
使用
new MaterialApp( onGenerateTitle: (context){ return 'Flutter應用'; }, );
11 . color
該顏色為Android中程序切換中應用圖標背景的顏色,當應用圖標背景為透明時
使用
new MaterialApp( color: Colors.blue, )
12 . theme
應用程序的主題,各種的定制顏色都可以設置,用於程序主題切換
使用
new MaterialApp( theme: new ThemeData( //主題色 primarySwatch: Colors.blue, ), );
13 . locale
當前區域,如果為null則使用系統區域 一般用於語言切換使用
//傳入兩個參數,語言代碼,國家代碼 new MaterialApp( Locale('yy','zh'), ); //源碼糾正,一些曾經用過的代碼(注釋后面的日期為不再使用的日期),源碼會自動糾正 //來看一下源碼 //languageCode 第一個參數 switch (languageCode) { case 'in': return 'id'; // Indonesian; deprecated 1989-01-01 case 'iw': return 'he'; // Hebrew; deprecated 1989-01-01 case 'ji': return 'yi'; // Yiddish; deprecated 1989-01-01 case 'jw': return 'jv'; // Javanese; deprecated 2001-08-13 case 'mo': return 'ro'; // Moldavian, Moldovan; deprecated 2008-11-22 case 'aam': return 'aas'; // Aramanik; deprecated 2015-02-12 case 'adp': return 'dz'; // Adap; deprecated 2015-02-12 case 'aue': return 'ktz'; // =/Kx'au//'ein; deprecated 2015-02-12 case 'ayx': return 'nun'; // Ayi (China); deprecated 2011-08-16 case 'bgm': return 'bcg'; // Baga Mboteni; deprecated 2016-05-30 case 'bjd': return 'drl'; // Bandjigali; deprecated 2012-08-12 case 'ccq': return 'rki'; // Chaungtha; deprecated 2012-08-12 case 'cjr': return 'mom'; // Chorotega; deprecated 2010-03-11 case 'cka': return 'cmr'; // Khumi Awa Chin; deprecated 2012-08-12 case 'cmk': return 'xch'; // Chimakum; deprecated 2010-03-11 case 'coy': return 'pij'; // Coyaima; deprecated 2016-05-30 case 'cqu': return 'quh'; // Chilean Quechua; deprecated 2016-05-30 case 'drh': return 'khk'; // Darkhat; deprecated 2010-03-11 case 'drw': return 'prs'; // Darwazi; deprecated 2010-03-11 case 'gav': return 'dev'; // Gabutamon; deprecated 2010-03-11 case 'gfx': return 'vaj'; // Mangetti Dune !Xung; deprecated 2015-02-12 case 'ggn': return 'gvr'; // Eastern Gurung; deprecated 2016-05-30 case 'gti': return 'nyc'; // Gbati-ri; deprecated 2015-02-12 case 'guv': return 'duz'; // Gey; deprecated 2016-05-30 case 'hrr': return 'jal'; // Horuru; deprecated 2012-08-12 case 'ibi': return 'opa'; // Ibilo; deprecated 2012-08-12 case 'ilw': return 'gal'; // Talur; deprecated 2013-09-10 case 'jeg': return 'oyb'; // Jeng; deprecated 2017-02-23 case 'kgc': return 'tdf'; // Kasseng; deprecated 2016-05-30 case 'kgh': return 'kml'; // Upper Tanudan Kalinga; deprecated 2012-08-12 case 'koj': return 'kwv'; // Sara Dunjo; deprecated 2015-02-12 case 'krm': return 'bmf'; // Krim; deprecated 2017-02-23 case 'ktr': return 'dtp'; // Kota Marudu Tinagas; deprecated 2016-05-30 case 'kvs': return 'gdj'; // Kunggara; deprecated 2016-05-30 case 'kwq': return 'yam'; // Kwak; deprecated 2015-02-12 case 'kxe': return 'tvd'; // Kakihum; deprecated 2015-02-12 case 'kzj': return 'dtp'; // Coastal Kadazan; deprecated 2016-05-30 case 'kzt': return 'dtp'; // Tambunan Dusun; deprecated 2016-05-30 case 'lii': return 'raq'; // Lingkhim; deprecated 2015-02-12 case 'lmm': return 'rmx'; // Lamam; deprecated 2014-02-28 case 'meg': return 'cir'; // Mea; deprecated 2013-09-10 case 'mst': return 'mry'; // Cataelano Mandaya; deprecated 2010-03-11 case 'mwj': return 'vaj'; // Maligo; deprecated 2015-02-12 case 'myt': return 'mry'; // Sangab Mandaya; deprecated 2010-03-11 case 'nad': return 'xny'; // Nijadali; deprecated 2016-05-30 case 'nnx': return 'ngv'; // Ngong; deprecated 2015-02-12 case 'nts': return 'pij'; // Natagaimas; deprecated 2016-05-30 case 'oun': return 'vaj'; // !O!ung; deprecated 2015-02-12 case 'pcr': return 'adx'; // Panang; deprecated 2013-09-10 case 'pmc': return 'huw'; // Palumata; deprecated 2016-05-30 case 'pmu': return 'phr'; // Mirpur Panjabi; deprecated 2015-02-12 case 'ppa': return 'bfy'; // Pao; deprecated 2016-05-30 case 'ppr': return 'lcq'; // Piru; deprecated 2013-09-10 case 'pry': return 'prt'; // Pray 3; deprecated 2016-05-30 case 'puz': return 'pub'; // Purum Naga; deprecated 2014-02-28 case 'sca': return 'hle'; // Sansu; deprecated 2012-08-12 case 'skk': return 'oyb'; // Sok; deprecated 2017-02-23 case 'tdu': return 'dtp'; // Tempasuk Dusun; deprecated 2016-05-30 case 'thc': return 'tpo'; // Tai Hang Tong; deprecated 2016-05-30 case 'thx': return 'oyb'; // The; deprecated 2015-02-12 case 'tie': return 'ras'; // Tingal; deprecated 2011-08-16 case 'tkk': return 'twm'; // Takpa; deprecated 2011-08-16 case 'tlw': return 'weo'; // South Wemale; deprecated 2012-08-12 case 'tmp': return 'tyj'; // Tai Mène; deprecated 2016-05-30 case 'tne': return 'kak'; // Tinoc Kallahan; deprecated 2016-05-30 case 'tnf': return 'prs'; // Tangshewi; deprecated 2010-03-11 case 'tsf': return 'taj'; // Southwestern Tamang; deprecated 2015-02-12 case 'uok': return 'ema'; // Uokha; deprecated 2015-02-12 case 'xba': return 'cax'; // Kamba (Brazil); deprecated 2016-05-30 case 'xia': return 'acn'; // Xiandao; deprecated 2013-09-10 case 'xkh': return 'waw'; // Karahawyana; deprecated 2016-05-30 case 'xsj': return 'suj'; // Subi; deprecated 2015-02-12 case 'ybd': return 'rki'; // Yangbye; deprecated 2012-08-12 case 'yma': return 'lrr'; // Yamphe; deprecated 2012-08-12 case 'ymt': return 'mtm'; // Mator-Taygi-Karagas; deprecated 2015-02-12 case 'yos': return 'zom'; // Yos; deprecated 2013-09-10 case 'yuu': return 'yug'; // Yugh; deprecated 2014-02-28 default: return languageCode; } //_countryCode 第二個參數 switch (_countryCode) { case 'BU': return 'MM'; // Burma; deprecated 1989-12-05 case 'DD': return 'DE'; // German Democratic Republic; deprecated 1990-10-30 case 'FX': return 'FR'; // Metropolitan France; deprecated 1997-07-14 case 'TP': return 'TL'; // East Timor; deprecated 2002-05-20 case 'YD': return 'YE'; // Democratic Yemen; deprecated 1990-08-14 case 'ZR': return 'CD'; // Zaire; deprecated 1997-07-14 default: return regionCode; }
14 . localizationsDelegates
本地化委托,用於更改Flutter Widget默認的提示語,按鈕text等
使用
new MaterialApp( localizationsDelegates: [ MyLocalizationsDelegates(), ], locale: Locale('zh','cn'), ); class MyLocalizationsDelegates extends LocalizationsDelegate <MaterialLocalizations>{ @override bool isSupported(Locale locale) { //是否支持該locale,如果不支持會報異常 if(locale == const Locale('zh','cn')){ return true; } return false; } @override//是否需要重載 bool shouldReload(LocalizationsDelegate old) => false; @override Future<MaterialLocalizations> load(Locale locale) { //加載本地化 return new SynchronousFuture(new MyLocalizations(locale)); } } //本地化實現,繼承DefaultMaterialLocalizations class MyLocalizations extends DefaultMaterialLocalizations{ final Locale locale; MyLocalizations(this.locale, ); @override String get okButtonLabel { if(locale == const Locale('zh','cn')){ return '好的'; }else{ return super.okButtonLabel; } } @override String get backButtonTooltip { if(locale == const Locale('zh','cn')){ return '返回'; }else{ return super.okButtonLabel; } } }
15 . localeResolutionCallback
當傳入的是不支持的語種,可以根據這個回調,返回相近,並且支持的語種
使用
16 . supportedLocales
傳入支持的語種數組
17 . debugShowMaterialGrid
debug模式下是否顯示材質網格,傳入bool類型,使用就不寫了
18 . showPerformanceOverlay
當為true時應用程序頂部覆蓋一層GPU和UI曲線圖,可即時查看當前流暢度情況
19 . checkerboardRasterCacheImages
當為true時,打開光柵緩存圖像的棋盤格
20 . checkerboardOffscreenLayers
當為true時,打開呈現到屏幕位圖的層的棋盤格
21 . showSemanticsDebugger
當為true時,打開Widget邊框,類似Android開發者模式中顯示布局邊界
22 . debugShowCheckedModeBanner
當為true時,在debug模式下顯示右上角的debug字樣的橫幅,false即為不顯示
三,Scaffold屬性介紹
1. appBar:
顯示在界面頂部的一個 AppBar,也就是 Android 中的 ActionBar 、Toolbar
2. body:
當前界面所顯示的主要內容 Widget
3. floatingActionButton:
紙墨設計中所定義的 FAB,界面的主要功能按鈕
4. persistentFooterButtons:
固定在下方顯示的按鈕,比如對話框下方的確定、取消按鈕
5. drawer:
側邊欄控件
6 .backgroundColor:
內容的背景顏色,默認使用的是 ThemeData.scaffoldBackgroundColor 的值
7. bottomNavigationBar:
顯示在頁面底部的導航欄
8. 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 的 build 函數中,使用 build 的 BuildContext 參數是可以的:
@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!'), )); }, ); }
如果 build 函數返回一個 Scaffold 對象,則由於 Scaffold 對象是這個 Widget 的子對象,所以使用這個 build 的 BuildContext 參數是不能查找到 ScaffoldState 對象的,這個時候,通過在 Scaffold 中使用一個 Builder 來提供一個新的 BuildConext :
@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!'), )); }, ), ); }, ), ); }
另外還可以把 build 函數中的 Widget 分別創建,分別引入新的 BuildContext 來獲取 Scaffold。
