Flutter基礎控件介紹

StatefulWidget

動態組件,開發中須要改變狀態,使用動態組件html

StatelessWidget

靜態組件,定義後不會再改變算法

組件按照功能分類

1. 基礎類組件

基礎組件

Text(文本),Image(圖片),xxButton(按鈕),TextField(輸入框),Form(表單)數組

Text('Hello World');服務器

Form

單獨說一下Form組件微信

​ 實際業務中,在正式向服務器提交數據前,都會對各個輸入框數據進行合法性校驗,可是對每個TextField都分別進行校驗將會是一件很麻煩的事。還有,若是用戶想清除一組TextField的內容,除了一個一個清除有沒有什麼更好的辦法呢?爲此,Flutter提供了一個Form widget,它能夠對輸入框進行分組,而後進行一些統一操做,如輸入內容校驗、輸入框重置以及輸入內容保存。less

​ Form的子孫元素必須是FormField類型,FormField是一個抽象類,定義幾個屬性,FormState內部經過它們來完成操做。函數

詳細佈局

2. 佈局類組件

Row(水平線性佈局),Column(垂直線性佈局),Flex(彈性佈局),Wrap|Flow(流式佈局),Stack|Positioned(層疊佈局)性能

線性佈局(Row、Column)
Column(
 crossAxisAlignment: CrossAxisAlignment.start,//子控件對齊方式
 mainAxisSize: MainAxisSize.max,    //自身大小
 children: <Widget>[],	//子控件
)
複製代碼
彈性佈局(Flex)
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平分。字體

流式佈局(Wrap、Flow)
  • Wrap直接使用,超過屏幕自動換行
  • Flow須要本身算,性能較好,換行規則本身定

Flow由於計算複雜使用較少,優先考慮Wrap是否能實現 詳細

層疊佈局(Stack、Positioned)
  • Stack相似Android中的FrameLayout,子Widget根據到四個角的位置來肯定自己的位置,容許子Widget堆疊。
  • Flutter中聯合使用Stack和Positioned來實現絕對定位,Stack容許子Widget堆疊,Positioned能夠給子Widget定位。

依據Flutter中的萬物皆Widget,因此Positioned這個Widget是一個設置位置的Widget,目的只是給子Widget設置位置。

3. 容器類組件

Padding(添加補白),ConstrainedBox|SizedBox(限制類容器),DecoratedBox(裝飾類容器),Transform(變換),Container,其餘

​ 佈局類Widget和容器類Widget的區別

  1. 佈局類Widget通常接收一個Widget數組(children),直接或間接繼承自(包含)MultiChildRenderObjectWidget,容器類Widget通常只須要接收一個Widget(child),直接或間接繼承自(包含)SingleChildRenderObjectWidget;
  2. 佈局類Widget是按照必定的排列方式來對其子Widget進行排列;而容器類Widget通常只是包裝其子Widget,對其添加一些修飾(補白或背景色等)、變換(旋轉或剪裁等)、或限制(大小等)。
Padding

​ 能夠給子節點添加補白,Flutter中給Widget添加間距也單獨抽出Widget

限制類容器(ConstrainedBox、SizedBox)

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)
複製代碼
裝飾容器(DecoratedBox)
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、RotateBox)

​ Transform能夠實現4D矩陣變換(Matrix4)、位移(offset)、旋轉(rotate)、縮放(scale);

注意:Transform只應用於繪製階段,不該用於layout階段,因此不管對子Widget作何種變換,其在屏幕上的位置和佔用空間的大小是不會變的

RotateBox和Transform的功能相似,可是它做用於layout階段,會影響子Widget的位置和佔用空間大小。

Container

​ Container是各類DecoratedBox、ConstrainedBox、Transform、Padding、Align等widget的一個組合widget,能夠同時實現裝飾、變換、限制的功能,

此外margin的補白是在容器外部,而padding的補白是在容器內部

其餘 Scaffold

​ Scaffold,由Flutter Material庫提供,是一個路由頁的骨架,能夠很是容易的拼裝出一個完整的頁面

​ AppBar是一個Material風格的導航欄,它能夠設置標題、導航欄菜單、底部Tab等

​ TabBar生成一個靜態的菜單,TabBarView配合TabBar實現左右切換的View,抽屜菜單Drawer,FloatingActionButton懸浮在頁面的某一個位置做爲某種經常使用動做的快捷入口

4.可滾動Widget

SingleChildScrollView,ListView,GridView,CustomScrollView,滾動監聽和控制ScrollController。

​ 當內容超過顯示窗口(ViewPort)的時候,Flutter就會提示Overflow錯誤,所以須要滾動Widget,可滾動的Widget都直接或者間接包含Scrollable widget。

SingleChildScrollView

​ 相似Android中的ScrollView,只接收一個子Widget

ListView

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怎樣響應用戶的操做,好比滑動完擡起手指,或滑動到邊界時如何顯示

  • ClampingScrollPhysics:Android下微光效果。
  • BouncingScrollPhysics:iOS下彈性效果。

​ 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,用於生成分割線。

GridView

​ 基本和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

​ CustomScrollView是可使用Sliver自定義滾動模型(效果)的widget。CustomScrollView能夠把彼此獨立的可滾動的widget(Sliver)「粘」起來。

​ 可滾動的widget如ListView,GridView都有對應的Sliver實現SliverList,SliverGrid。對於大多數Sliver來講,他們和可滾動的widget的區別是Sliver不包含Scrollable widget,自己Sliver不包含滾動模型,這些widget公用CustomScrollView的Scrollable,最終實現統一滾動效果。

詳細

滾動監聽及控制ScrollController

​ 能夠經過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則繼續向上傳遞。

5.功能型widget

​ 功能性widget是指不會影響UI佈局及外觀的widget,一般有必定功能,如事件監聽,數據存儲等。

導航事件攔截(WillPopScope)

​ 經過WillPopScope實現返回按鈕攔截,包括Android的物理返回鍵和導航返回按鈕。在onWillPop回調函數中處理相關邏輯,返回true時當前路由出棧,返回false時,當前路由不出棧。

數據共享(InheritedWidget)

​ 能夠高效的將數據在widget樹中下傳遞、共享。例如正是經過InheritedWidget來共享Theme(主題)和Locale(當前語言環境)信息。

主題(Theme)

​ Theme widget能夠爲Material App定義主題數據(ThemeData),Material組件庫裏不少Widget都使用了主題數據,如導航欄顏色、標題字體、Icon樣式等。Theme會經過InheritedWidget來爲其子樹widget共享樣式數據。

​ 可定義的主題數據都在ThemeData中,能夠經過Theme.of(context)獲取當前的ThemeData。

歡迎關注微信公衆號:Flutter入門

相關文章
相關標籤/搜索