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,
})
複製代碼
使用示例網絡
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
進行設置, 後面會詳解app
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,
})
複製代碼
歡迎您掃一掃下面的微信公衆號,訂閱個人博客!