Flutter
一切皆Widget
的核心思想, 爲咱們提供了兩種主題風格CupertinoApp
: 一個封裝了不少iOS
風格的小部件,通常做爲頂層widget
使用MaterialApp
: 一個封裝了不少安卓風格的小部件,通常做爲頂層widget
使用, 下面咱們先看下這個Widget
這裏咱們先看看MaterialApp
的構造函數和相關函數html
const MaterialApp({ Key key, // 導航主鍵, GlobalKey<NavigatorState> this.navigatorKey, // 主頁, Widget this.home, // 路由 this.routes = const <String, WidgetBuilder>{}, // 初始化路由, String this.initialRoute, // 構造路由, RouteFactory this.onGenerateRoute, // 爲止路由, RouteFactory this.onUnknownRoute, // 導航觀察器 this.navigatorObservers = const <NavigatorObserver>[], // widget的構建 this.builder, // APP的名字 this.title = '', // GenerateAppTitle, 每次在WidgetsApp構建時都會從新生成 this.onGenerateTitle, // 背景顏色 this.color, // 主題, ThemeData this.theme, // app語言支持, Locale this.locale, // 多語言代理, Iterable<LocalizationsDelegate<dynamic>> this.localizationsDelegates, // flutter.widgets.widgetsApp.localeListResolutionCallback this.localeListResolutionCallback, // flutter.widgets.widgetsApp.localeResolutionCallback this.localeResolutionCallback, // 支持的多語言, Iterable<Locale> this.supportedLocales = const <Locale>[Locale('en', 'US')], // 是否顯示網格 this.debugShowMaterialGrid = false, // 是否打開性能監控,覆蓋在屏幕最上面 this.showPerformanceOverlay = false, // 是否打開柵格緩存圖像的檢查板 this.checkerboardRasterCacheImages = false, // 是否打開顯示到屏幕外位圖的圖層的檢查面板 this.checkerboardOffscreenLayers = false, // 是否打開覆蓋圖,顯示框架報告的可訪問性信息 顯示邊框 this.showSemanticsDebugger = false, // 是否顯示右上角的Debug標籤 this.debugShowCheckedModeBanner = true, }) 複製代碼
須要注意的幾點git
home
首頁指定了,routes
裏面就不能有'/'
的根路由了,會報錯,/
指定的根路由就多餘了home
指定具體的頁面,那routes
裏面就有/
來指定根路由home
,就會從home
進入home
,有routes
,而且routes
指定了入口'/'
,就會從routes
的/
進入onGenerateRoute
,就會進入生成的路由onUnknownRoute
,不明因此的路由,好比網絡鏈接失敗,能夠進入斷網的頁面Navigation.of(context).pushNamed
跳轉的路由key
:路由名字value
:對應的Widget
routes: { '/home': (BuildContext content) => Home(), '/mine': (BuildContext content) => Mine(), }, 複製代碼
routes
的key
, 跳轉的是對應的Widget
(若是該Widget
有Scaffold.AppBar
,並不作任何修改,左上角有返回鍵)routes: { '/home': (BuildContext content) => Home(), '/mine': (BuildContext content) => Mine(), }, initialRoute: '/mine', 複製代碼
當經過Navigation.of(context).pushNamed
跳轉路由時, 在routes
查找不到時,會調用該方法github
onGenerateRoute: (RouteSettings setting) { return MaterialPageRoute( settings: setting, builder: (BuildContext content) => Text('生成一個路由') ); }, 複製代碼
未知路由, 效果跟onGenerateRoute
同樣, 在未設置onGenerateRoute
的狀況下, 纔會去調用onUnknownRoute
數組
onUnknownRoute: (RouteSettings setting) { return MaterialPageRoute( settings: setting, builder: (BuildContext content) => Text('這是一個未知路由') ); }, 複製代碼
Navigator
的相關方法時,會回調相關的操做push
,pop
,remove
,replace
是能夠拿到當前路由和後面路由的信息route.settings.name
// navigatorObservers: [HomeObserver()], // 繼承NavigatorObserver class HomeObserver extends NavigatorObserver { @override void didPush(Route route, Route previousRoute) { super.didPush(route, previousRoute); // 獲取路由的名字 print('name = ${route.settings.name}'); // 獲取返回的內容 print('reaule = ${route.currentResult}'); } } 複製代碼
若是設置了這個參數, 那麼將會優先渲染這個builder
, 而不會在走路由緩存
builder: (BuildContext content, Widget widget) => Text('builder'), 複製代碼
Android
上,標題顯示在任務管理器的應用程序快照上方,當用戶按下「最近的應用程序」按鈕時會顯示這些快照iOS
上,沒法使用此值。來自應用程序的Info.plist
的CFBundleDisplayName
在任什麼時候候都會被引用,不然就會引用CFBundleName
onGenerateTitle
用於建立iOS
風格應用的頂層組件, 相關屬性和MaterialApp
相比只是少了theme
和debugShowMaterialGrid
, 其餘屬性都同樣, 以下所示安全
const CupertinoApp({ Key key, this.navigatorKey, this.home, this.routes = const <String, WidgetBuilder>{}, this.initialRoute, this.onGenerateRoute, this.onUnknownRoute, this.navigatorObservers = const <NavigatorObserver>[], this.builder, this.title = '', this.onGenerateTitle, this.color, this.locale, this.localizationsDelegates, this.localeListResolutionCallback, this.localeResolutionCallback, this.supportedLocales = const <Locale>[Locale('en', 'US')], this.showPerformanceOverlay = false, this.checkerboardRasterCacheImages = false, this.checkerboardOffscreenLayers = false, this.showSemanticsDebugger = false, this.debugShowCheckedModeBanner = true, }) 複製代碼
使用示例以下bash
return CupertinoApp( title: 'Cupertino App', color: Colors.red, home: CupertinoPageScaffold( backgroundColor: Colors.yellow, resizeToAvoidBottomInset: true, navigationBar: CupertinoNavigationBar( middle: Text('Cupertino App Bar'), backgroundColor: Colors.blue, ), child: Center( child: Container( child: Text('Hello World'), ), ), ), ); 複製代碼
一個iOS
風格的頁面的基本佈局結構。包含內容和導航欄微信
const CupertinoPageScaffold({ Key key, // 設置導航欄, 後面會詳解 this.navigationBar, // 設置內容頁面的背景色 this.backgroundColor = CupertinoColors.white, // 子widget是否應該自動調整自身大小以適應底部安全距離 this.resizeToAvoidBottomInset = true, @required this.child, }) 複製代碼
const CupertinoNavigationBar({ Key key, //導航欄左側組件 this.leading, //是否顯示左邊組件, 好像無效 this.automaticallyImplyLeading = true, //是否顯示中間組件, 好像無效 this.automaticallyImplyMiddle = true, //導航欄左側組件的右邊的文本, 好像無效 this.previousPageTitle, // 導航欄中間組件 this.middle, // 導航欄右側組件 this.backgroundColor = _kDefaultNavBarBackgroundColor, // 設置左右組件的內邊距, EdgeInsetsDirectional this.padding, //左側默認組件和左側組件右邊文本的顏色 this.actionsForegroundColor = CupertinoColors.activeBlue, this.transitionBetweenRoutes = true, this.heroTag = _defaultHeroTag, }) 複製代碼
使用示例markdown
return CupertinoApp( title: 'Cupertino App', color: Colors.red, debugShowCheckedModeBanner: false, home: CupertinoPageScaffold( backgroundColor: Colors.yellow, resizeToAvoidBottomInset: true, navigationBar: CupertinoNavigationBar( leading: Icon(Icons.person), automaticallyImplyLeading: false, automaticallyImplyMiddle: false, previousPageTitle: '返回', middle: Text('Cupertino App Bar'), trailing: Icon(Icons.money_off), border: Border.all(), backgroundColor: Colors.white, padding: EdgeInsetsDirectional.fromSTEB(10, 10, 10, 10), actionsForegroundColor: Colors.red, transitionBetweenRoutes: false, heroTag: Text('data'), ), child: Center( child: Container( child: Text('Hello World'), ), ), ), ); 複製代碼
Scaffold
一般被用做MaterialApp
的子Widget
(安卓風格),它會填充可用空間,佔據整個窗口或設備屏幕Scaffold
提供了大多數應用程序都應該具有的功能,例如頂部的appBar
,底部的bottomNavigationBar
,隱藏的側邊欄drawer
等const Scaffold({ Key key, // 顯示在界面頂部的一個AppBar this.appBar, // 當前界面所顯示的主要內容Widget this.body, // 懸浮按鈕, 默認在右下角位置顯示 this.floatingActionButton, // 設置懸浮按鈕的位置 this.floatingActionButtonLocation, // 懸浮按鈕出現消失的動畫 this.floatingActionButtonAnimator, // 在底部呈現一組button,顯示於[bottomNavigationBar]之上,[body]之下 this.persistentFooterButtons, // 一個垂直面板,顯示於左側,初始處於隱藏狀態 this.drawer, // 一個垂直面板,顯示於右側,初始處於隱藏狀態 this.endDrawer, // 出現於底部的一系列水平按鈕 this.bottomNavigationBar, // 底部的持久化提示框 this.bottomSheet, // 背景色 this.backgroundColor, // 從新計算佈局空間大小 this.resizeToAvoidBottomPadding = true, // 是否顯示到底部, 默認爲true將顯示到頂部狀態欄 this.primary = true, }) 複製代碼
設置導航欄, 接受一個抽象類PreferredSizeWidget
, 這裏使用其子類AppBar
進行設置, 後面會詳解網絡
FloatingActionButton
設置FloatingActionButton
是Material
設計規範中的一種特殊Button
,一般懸浮在頁面的某一個位置做爲某種經常使用動做的快捷入口, 後面會詳解設置懸浮按鈕的位置, 接受一個抽象類FloatingActionButtonLocation
// 右下角, 距離底部有一點距離, 默認值 static const FloatingActionButtonLocation endFloat = _EndFloatFabLocation(); // 中下方, 距離底部有一點距離 static const FloatingActionButtonLocation centerFloat = _CenterFloatFabLocation(); // 右下角, 距離底部沒有間距 static const FloatingActionButtonLocation endDocked = _EndDockedFloatingActionButtonLocation(); // 中下方, 距離底部沒有間距 static const FloatingActionButtonLocation centerDocked = _CenterDockedFloatingActionButtonLocation(); 複製代碼
在Material Design
中,通常用來處理界面中最經常使用,最基礎的用戶動做。它通常出如今屏幕內容的前面,一般是一個圓形,中間有一個圖標, 有如下幾種構造函數
const FloatingActionButton({ Key key, this.child, // 文字解釋, 按鈕唄長按時顯示 this.tooltip, // 前景色 this.foregroundColor, // 背景色 this.backgroundColor, // hero效果使用的tag,系統默認會給全部FAB使用同一個tag,方便作動畫效果 this.heroTag = const _DefaultHeroTag(), // 未點擊時陰影值,默認6.0 this.elevation = 6.0, // 點擊時陰影值,默認12.0 this.highlightElevation = 12.0, // 點擊事件監聽 @required this.onPressed, // 是否爲「mini」類型,默認爲false this.mini = false, // 設置陰影, 設置shape時,默認的elevation將會失效,默認爲CircleBorder this.shape = const CircleBorder(), // 剪切樣式 this.clipBehavior = Clip.none, // 設置點擊區域大小的樣式, MaterialTapTargetSize的枚舉值 this.materialTapTargetSize, // 是否爲」extended」類型 this.isExtended = false, }) 複製代碼
mini
類型,默認爲false
FloatingActionButton
分爲三種類型:regular
, mini
, extended
regular
和mini
兩種類型經過默認的構造方法實現, 只有圖片const BoxConstraints _kSizeConstraints = const BoxConstraints.tightFor( width: 56.0, height: 56.0, ); const BoxConstraints _kMiniSizeConstraints = const BoxConstraints.tightFor( width: 40.0, height: 40.0, ); const BoxConstraints _kExtendedSizeConstraints = const BoxConstraints( minHeight: 48.0, maxHeight: 48.0, ); 複製代碼
extended
類型, 設置爲true
便可extended
構造函數建立該類型FloatingActionButton.extended({ Key key, this.tooltip, this.foregroundColor, this.backgroundColor, this.heroTag = const _DefaultHeroTag(), this.elevation = 6.0, this.highlightElevation = 12.0, @required this.onPressed, this.shape = const StadiumBorder(), this.isExtended = true, this.materialTapTargetSize, this.clipBehavior = Clip.none, // 設置圖片 @required Widget icon, // 設置文字 @required Widget label, }) 複製代碼
從參數上看差別並不大,只是把默認構造方法中的child
換成了icon
和label
,不過經過下面的代碼能夠看到,傳入的label
和icon
也是用來構建child
的,不過使用的是Row
來作一層包裝而已
AppBar
是一個Material
風格的導航欄,它能夠設置標題、導航欄菜單、底部Tab
等
AppBar({ Key key, // 導航欄左側weidget this.leading, // 若是leading爲null,是否自動實現默認的leading按鈕 this.automaticallyImplyLeading = true, // 導航欄標題 this.title, // 導航欄右側按鈕, 接受一個數組 this.actions, // 一個顯示在AppBar下方的控件,高度和AppBar高度同樣,能夠實現一些特殊的效果,該屬性一般在SliverAppBar中使用 this.flexibleSpace, // 一個AppBarBottomWidget對象, 設置TabBar this.bottom, //中控件的z座標順序,默認值爲4,對於可滾動的SliverAppBar,當 SliverAppBar和內容同級的時候,該值爲0,當內容滾動 SliverAppBar 變爲 Toolbar 的時候,修改elevation的值 this.elevation = 4.0, // 背景顏色,默認值爲 ThemeData.primaryColor。改值一般和下面的三個屬性一塊兒使用 this.backgroundColor, // 狀態欄的顏色, 黑白兩種, 取值: Brightness.dark this.brightness, // 設置導航欄上圖標的顏色、透明度、和尺寸信息 this.iconTheme, // 設置導航欄上文字樣式 this.textTheme, // 導航欄的內容是否顯示在頂部, 狀態欄的下面 this.primary = true, // 標題是否居中顯示,默認值根據不一樣的操做系統,顯示方式不同 this.centerTitle, // 標題間距,若是但願title佔用全部可用空間,請將此值設置爲0.0 this.titleSpacing = NavigationToolbar.kMiddleSpacing, // 應用欄的工具欄部分透明度 this.toolbarOpacity = 1.0, // 底部導航欄的透明度設置 this.bottomOpacity = 1.0, }) 複製代碼
導航欄左側weidget
final Widget leading; // 示例 leading: Icon(Icons.home), 複製代碼
導航欄右側按鈕, 接受一個數組
final List<Widget> actions; // 示例 actions: <Widget>[ Icon(Icons.add), Icon(Icons.home), ], 複製代碼
狀態欄的顏色, 黑白兩種
// 狀態欄白色 brightness: Brightness.dark, // 狀態欄黑色 brightness: Brightness.light, 複製代碼
設置導航欄上圖標的顏色、透明度、和尺寸信息
const IconThemeData({this.color, double opacity, this.size}) // 示例 iconTheme: IconThemeData(color: Colors.white, opacity: 0.56, size: 30), 複製代碼
AppBar
中經過bottom
屬性來添加一個導航欄底部tab
按鈕組, 接受一個PreferredSizeWidget
類型PreferredSizeWidget
是一個抽象類, 這裏咱們使用TabBar
class TabBar extends StatefulWidget implements PreferredSizeWidget { const TabBar({ Key key, // 數組,顯示的標籤內容,通常使用Tab對象,固然也能夠是其餘的Widget @required this.tabs, // TabController對象 this.controller, // 是否可滾動 this.isScrollable = false, // 指示器顏色 this.indicatorColor, // 指示器高度 this.indicatorWeight = 2.0, // 指示器內邊距 this.indicatorPadding = EdgeInsets.zero, // 設置選中的樣式decoration,例如邊框等 this.indicator, // 指示器大小, 枚舉值TabBarIndicatorSize this.indicatorSize, // 選中文字顏色 this.labelColor, // 選中文字樣式 this.labelStyle, // 文字內邊距 this.labelPadding, // 未選中文字顏色 this.unselectedLabelColor, // 未選中文字樣式 this.unselectedLabelStyle, }) } // Tab的構造函數 const Tab({ Key key, // 文本 this.text, // 圖標 this.icon, // 子widget this.child, }) 複製代碼
效果以下
相關代碼以下
void main(List<String> args) => runApp(NewApp()); class NewApp extends StatefulWidget { @override State<StatefulWidget> createState() { // TODO: implement createState return App(); } } class App extends State<NewApp> with SingleTickerProviderStateMixin { List tabs = ['語文', '數學', '英語', '政治', '歷史', '地理', '物理', '化學', '生物']; TabController _tabController; @override void initState() { super.initState(); _tabController = TabController(initialIndex: 0, length: tabs.length, vsync: this); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar( title: Text('CoderTitan'), backgroundColor: Colors.blueAccent, brightness: Brightness.dark, centerTitle: true, bottom: TabBar( controller: _tabController, tabs: tabs.map((e) => Tab(text: e)).toList(), isScrollable: true, indicatorColor: Colors.red, indicatorWeight: 2, indicatorSize: TabBarIndicatorSize.label, labelColor: Colors.orange, unselectedLabelColor: Colors.white, labelStyle: TextStyle(fontSize: 18, color: Colors.orange), unselectedLabelStyle: TextStyle(fontSize: 15, color: Colors.white), ), ), body: TabBarView( controller: _tabController, children: tabs.map((e) { return Container( alignment: Alignment.center, child: Text(e, style:TextStyle(fontSize: 50)), ); }).toList(), ), ), debugShowCheckedModeBanner: false, ); } } 複製代碼
Scaffold
中有一個屬性bottomNavigationBar
用於設置最底部的tabbar
導航欄Material
組件庫提供的BottomNavigationBar
和BottomNavigationBarItem
兩個Widget
來實現Material風格的底部導航欄BottomNavigationBar({ Key key, // 子widget數組 @required this.items, // 每個item的點擊事件 this.onTap, // 當前選中的索引 this.currentIndex = 0, // 類型 BottomNavigationBarType type, // 文字顏色 this.fixedColor, // 圖片大小 this.iconSize = 24.0, }) 複製代碼
包含全部子Widget
的數組
final List<BottomNavigationBarItem> items; const BottomNavigationBarItem({ // 未選中圖片 @required this.icon, // 標題 this.title, // 選中的圖片 Widget activeIcon, // 背景色 this.backgroundColor, }) 複製代碼
歡迎您掃一掃下面的微信公衆號,訂閱個人博客!