動態組件,開發中須要改變狀態,使用動態組件html
靜態組件,定義後不會再改變算法
Text(文本),Image(圖片),xxButton(按鈕),TextField(輸入框),Form(表單)數組
Text('Hello World');
服務器
單獨說一下Form組件微信
實際業務中,在正式向服務器提交數據前,都會對各個輸入框數據進行合法性校驗,可是對每個TextField都分別進行校驗將會是一件很麻煩的事。還有,若是用戶想清除一組TextField的內容,除了一個一個清除有沒有什麼更好的辦法呢?爲此,Flutter提供了一個Form widget,它能夠對輸入框進行分組,而後進行一些統一操做,如輸入內容校驗、輸入框重置以及輸入內容保存。less
Form的子孫元素必須是FormField類型,FormField是一個抽象類,定義幾個屬性,FormState內部經過它們來完成操做。函數
詳細佈局
Row(水平線性佈局),Column(垂直線性佈局),Flex(彈性佈局),Wrap|Flow(流式佈局),Stack|Positioned(層疊佈局)性能
Column(
crossAxisAlignment: CrossAxisAlignment.start,//子控件對齊方式
mainAxisSize: MainAxisSize.max, //自身大小
children: <Widget>[], //子控件
)
複製代碼
Flex(
direction: Axis.horizontal,
children: <Widget>[
Expanded(
child: Container(
height: 30,
color: Colors.red,),
flex: 1,),
Expanded(
child: Container(
height: 30,
color: Colors.blue,),
flex: 2,
),],),
複製代碼
Flex裏面的兩個Expanded按照1:2平分。字體
Flow由於計算複雜使用較少,優先考慮Wrap是否能實現 詳細
依據Flutter中的萬物皆Widget,因此Positioned這個Widget是一個設置位置的Widget,目的只是給子Widget設置位置。
Padding(添加補白),ConstrainedBox|SizedBox(限制類容器),DecoratedBox(裝飾類容器),Transform(變換),Container,其餘
佈局類Widget和容器類Widget的區別
能夠給子節點添加補白,Flutter中給Widget添加間距也單獨抽出Widget
ConstrainedBox用於添加對子Widget的限制
ConstrainedBox(
constraints: BoxConstraints(//用於設置限制條件
minWidth: double.infinity, //寬度儘量大
minHeight: 50.0 //最小高度爲50像素
),
child: Widget,)
複製代碼
SizedBox用於給子Widget指定固定的寬高
SizedBox(
width: 80.0,
height: 80.0,
child: redBox)
複製代碼
const DecoratedBox({
Decoration decoration,
DecorationPosition position = DecorationPosition.background,
Widget child})
複製代碼
使用Decoration的實現類去裝飾子Widget(BoxDecoration)
BoxDecoration({
Color color, //顏色
DecorationImage image,//圖片
BoxBorder border, //邊框
BorderRadiusGeometry borderRadius, //圓角
List<BoxShadow> boxShadow, //陰影,能夠指定多個
Gradient gradient, //漸變
BlendMode backgroundBlendMode, //背景混合模式
BoxShape shape = BoxShape.rectangle, //形狀
})
複製代碼
Transform能夠實現4D矩陣變換(Matrix4)、位移(offset)、旋轉(rotate)、縮放(scale);
注意:Transform只應用於繪製階段,不該用於layout階段,因此不管對子Widget作何種變換,其在屏幕上的位置和佔用空間的大小是不會變的
RotateBox和Transform的功能相似,可是它做用於layout階段,會影響子Widget的位置和佔用空間大小。
Container是各類DecoratedBox、ConstrainedBox、Transform、Padding、Align等widget的一個組合widget,能夠同時實現裝飾、變換、限制的功能,
此外margin的補白是在容器外部,而padding的補白是在容器內部
Scaffold,由Flutter Material庫提供,是一個路由頁的骨架,能夠很是容易的拼裝出一個完整的頁面
AppBar是一個Material風格的導航欄,它能夠設置標題、導航欄菜單、底部Tab等
TabBar生成一個靜態的菜單,TabBarView配合TabBar實現左右切換的View,抽屜菜單Drawer,FloatingActionButton懸浮在頁面的某一個位置做爲某種經常使用動做的快捷入口
SingleChildScrollView,ListView,GridView,CustomScrollView,滾動監聽和控制ScrollController。
當內容超過顯示窗口(ViewPort)的時候,Flutter就會提示Overflow錯誤,所以須要滾動Widget,可滾動的Widget都直接或者間接包含Scrollable widget。
相似Android中的ScrollView,只接收一個子Widget
ListView最經常使用的可滾動widget
ListView({
...
//可滾動widget公共參數
Axis scrollDirection = Axis.vertical,//滾動方向
bool reverse = false,//是否反向(從右到左)
ScrollController controller,//控制滾動位置和監聽滾動事件
bool primary,//是否使用Widget樹中默認的PrimaryScrollController
ScrollPhysics physics,//接收一個ScrollPhysics參數
EdgeInsetsGeometry padding,
//ListView各個構造函數的共同參數
double itemExtent,//強制item的高度,相對不設置會高效
bool shrinkWrap = false,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double cacheExtent,
//子widget列表
List<Widget> children = const <Widget>[],
})
複製代碼
physics:決定可滾動widget怎樣響應用戶的操做,好比滑動完擡起手指,或滑動到邊界時如何顯示
addAutomaticKeepAlives:是否將列表項(子Widget)包裹在AutomaticKeepAlive widget中,典型的,在一個懶加載列表中,若是列表項包裹在AutomaticKeepAlive中,列表項移出視口時該列表項不會GC,會使用KeepAliveNotification來保存其狀態。若是列表項本身維護KeepAlive狀態,則此項爲false。 addRepaintBoundaries:是否將列表項(子Widget)包裹在RepaintBoundary中。將列表項包裹在RepaintBoundary中能夠避免在滾動的時候重繪,但重繪開銷很是小的時候,不添加RepaintBoundary反而會高效。 ListView 的構造函數 默認構造函數
ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(20.0),
children: <Widget>[
const Text("Im dedicating every day to you"),
const Text("Domestic life was never quite my style"),
const Text("When you smile, you knock me out, I fall apart"),
const Text("And I thought I was so smart"),
],);
複製代碼
默認構造函數會把全部的子widget提早建立好。
ListView.builder構造函數
ListView.builder({
// ListView公共參數已省略
...
@required IndexedWidgetBuilder itemBuilder, //列表的構造器,返回一個Widget
int itemCount,//列表項的數量,null表示無限
...})
複製代碼
ListView.separated構造函數
比ListView.build多一個separatorBuilder,用於生成分割線。
基本和ListView相同,有個一SliverGridDelegate gridDelegate參數,用於控制子widget如何排列。 兩個實現類: SliverGridDelegateWithFixedCrossAxisCount 橫軸爲固定數量子元素, SliverGridDelegateWithMaxCrossAxisExtent 橫軸子元素爲固定最大長度的layout算法。
默認構造函數 GridView({})
GridView.count構造函數
內部使用SliverGridDelegateWithFixedCrossAxisCount去建立橫軸爲固定數量的GridView。
GridView.extent構造函數
內部使用了SliverGridDelegateWithMaxCrossAxisExtent去建立橫軸子元素爲固定最大長度的算法。
GridView.builder構造函數
GridView.builder(
...
@required SliverGridDelegate gridDelegate,
@required IndexedWidgetBuilder itemBuilder, //子widget構造方法
)
複製代碼
Pub上有一個包「flutter_staggered_grid_view」 ,它實現了一個交錯GridView的佈局,子widget大小不同。
CustomScrollView是可使用Sliver自定義滾動模型(效果)的widget。CustomScrollView能夠把彼此獨立的可滾動的widget(Sliver)「粘」起來。
可滾動的widget如ListView,GridView都有對應的Sliver實現SliverList,SliverGrid。對於大多數Sliver來講,他們和可滾動的widget的區別是Sliver不包含Scrollable widget,自己Sliver不包含滾動模型,這些widget公用CustomScrollView的Scrollable,最終實現統一滾動效果。
能夠經過ScrollController來控制Scrollable widget的滾動位置,滾動事件傳遞等。
ScrollController構造函數
ScrollController({
double initialScrollOffset = 0.0, //初始滾動位置
this.keepScrollOffset = true, //是否保存滾動位置
})
複製代碼
經常使用方法和屬性offset:可滾動組件當前滾動的位置;jumpTo(double offset)、animateTo(double offset) 跳轉到指定位置。
滾動監聽
ScrollController間接繼承自Listenable,能夠監聽滾動事件
controller.addListener(()=>print(controller.offset));
滾動位置恢復
PageStorage是用於保存頁面(路由)相關數據的Widget,是一個功能型widget,不影響子樹的UI外觀,它擁有一個存儲桶(bucket),子樹中的widget能夠經過指定不一樣的PageStorageKey來存儲各自的數據或狀態。
須要配合keepScrollOffset使用,爲true的時候,會記錄滾動位置。
當一個路由中包括多個Scrollable widget的時候,在進行一些跳轉操做後,滾動位置不能正確恢復,這時能夠顯式給Scrollable widget指定PageStoreKey來分別跟蹤。
並不是一個路由包含多個Scrollable widget時,就須要使用PageStoreKey分別跟蹤,由於它們都是StatefullWidget,只要widget沒有被從樹上detach掉,其state就不會銷燬(dispose),滾動位置就不會丟失。
ScrollPosition
ScrollController能夠被多個Scrollable widget使用,ScrollController會爲每一個Scrollable widget建立一個ScrollPosition,這些ScrollPosition保存在ScrollController的position中。ScrollPosition是真正保存滑動位置信息的對象,offset只是一個便捷屬性。
ScrollPosition有animateTo(),jumpTo(),來控制真正跳轉滾動位置的方法,ScrollController的兩個同名方法,最終會調用這兩個。
滾動監聽
Flutter widgets樹中的子widget能夠經過發送通知與父(包括祖)widget通訊,父widget也能夠經過NotificationListener widget來監聽本身關注的通知。
NotificationListener是一個widget,模板參數是想要關注的通知類型,若是省略,則全部類型的通知都會監聽。須要實現一個onNotification回調函數,實現監聽處理邏輯,返回布爾值,若是返回true,則事件中止向上傳遞,返回false則繼續向上傳遞。
功能性widget是指不會影響UI佈局及外觀的widget,一般有必定功能,如事件監聽,數據存儲等。
經過WillPopScope實現返回按鈕攔截,包括Android的物理返回鍵和導航返回按鈕。在onWillPop回調函數中處理相關邏輯,返回true時當前路由出棧,返回false時,當前路由不出棧。
能夠高效的將數據在widget樹中下傳遞、共享。例如正是經過InheritedWidget來共享Theme(主題)和Locale(當前語言環境)信息。
Theme widget能夠爲Material App定義主題數據(ThemeData),Material組件庫裏不少Widget都使用了主題數據,如導航欄顏色、標題字體、Icon樣式等。Theme會經過InheritedWidget來爲其子樹widget共享樣式數據。
可定義的主題數據都在ThemeData中,能夠經過Theme.of(context)獲取當前的ThemeData。
歡迎關注微信公衆號:Flutter入門