天天看點

Flutter(七)——多子元素元件:GridView,CustomScrollView,Flex,Wrap

本文目錄

    • 前言
    • GridView
    • CustomScrollView
    • Flex
    • Wrap

上一篇介紹了多元素元件:ListView,Scaffold,AppBar,Row,Column,這一節将接着上一篇博文,介紹GridView,CustomScrollView,Flex,以及Wrap多元素元件(下圖為CustomScrollView實作效果)

Flutter(七)——多子元素元件:GridView,CustomScrollView,Flex,Wrap

首先,就是GridView,它和ListView相似,隻不過表現形式為網格形式,可以把它看成Android的LayoutManager。如果GridView元件掌握的很好,那麼App界面也是會非常好看,給人賞心悅目。不過需要注意的是,GridView中的gridDelegate屬性,其類型是SliverGridDelegate,是一個抽象類,通過該類可以控制GridView的排列顯示方式,我們先來看看官方文檔的使用方式:

body: GridView.count(
        primary: false,
        padding: const EdgeInsets.all(20.0),
        crossAxisSpacing: 10.0,
        crossAxisCount: 2,
        children: <Widget>[
          const Text("11111111111111111111"),
          const Text("22222222222222222222"),
          const Text("33333333333333333333"),
          const Text("44444444444444444444"),
          const Text("55555555555555555555"),
          const Text("66666666666666666666"),
        ],
      ),
           

這裡我們沒有看到代碼中使用SliverGridDelegate,那麼它在哪裡呢?其實,在GridView.count中的構造函數裡已經傳入了預設的gridDelegate,通過開發工具我們進入它的源碼:

gridDelegate = SliverGridDelegateWithFixedCrossAxisCount(
         crossAxisCount: crossAxisCount,
         mainAxisSpacing: mainAxisSpacing,
         crossAxisSpacing: crossAxisSpacing,
         childAspectRatio: childAspectRatio,
       ),
           

源碼裡已經使用了SliverGridDelegateWithFixedCrossAxisCount。它有四個屬性,我們先來看看他們的定義:

屬性 取值
crossAxisCount 橫向軸子元素的數量
mainAxisSpacing 橫向軸之間的間距
crossAxisSpacing 子元素之間的間距
childAspectRatio 子元素的寬高比,比如2.0就表示寬度是高度的2倍

gridDelegate還支援SliverGridDelegateWithMaxCrossAxisExtent,同時GridView也和ListView一樣支援GridView.builder來建立,使用代碼與ListView差不多,這裡就不在贅述了,上面代碼實作效果如下:

Flutter(七)——多子元素元件:GridView,CustomScrollView,Flex,Wrap

在實際應用裡,布局情況并不是非此即彼,一般一個界面不會隻有一個滾動清單元件,很可能還有别的元件,這個時候CustomScrollView就有用處了,它的使用代碼如下:

return CustomScrollView(
      slivers: <Widget>[
        const SliverAppBar(
          pinned: true,//标題欄是否固定
          expandedHeight: 250.0,//合并的高度,預設是狀态欄的高度加AppBar的高度
          flexibleSpace: FlexibleSpaceBar(
            title: Text("我的标題"),
          ),
        ),
        SliverGrid(
            delegate: SliverChildBuilderDelegate((BuildContext context,int index){
              return Container(
                alignment: Alignment.center,
                color: Colors.teal[100*(index%9)],
                child: Text("第$index個"),
              );
            },childCount: 20),
            gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
                maxCrossAxisExtent: 200.0,//單個子Widget的水準最大寬度
                mainAxisSpacing: 10.0,//水準單個子Widget之間間距
                crossAxisSpacing: 10.0,//垂直單個子Widget之間間距
                childAspectRatio: 4.0,//寬高比
            )
        ),
        SliverFixedExtentList(
          itemExtent: 50.0,
          delegate: SliverChildBuilderDelegate((BuildContext context,int index){
            return Container(
              alignment: Alignment.center,
              color: Colors.lightBlue[100*(index%9)],
              child: Text("第$index個"),
            );
          }),
        ),
      ],
    );
           

這段代碼看起來非常複雜其實很好了解,在Scaffold中,Appbar等價于SliverAppBar,剛講解的GridView等價于SliverGrid,而ListView等價于SliverFixedExtentList,是以這是一個包含了二個滑動元件的一個布局容器,其他的代碼中有注釋,這裡就不贅述了。(顯示效果如博文首圖)

特别注意:轉換後的元件都是以“Sliver”開頭的,其本身是不具備滾動特性的,但是放在CustomScrollView中之後,則可以實作滾動的功能。

Flex英文意思是屈伸,活動,在Flutter裡面也就是彈性布局,該布局借鑒了前端裡的Flex布局方式。用法也十分簡單,我們可以在Flex中傳入一些參數,其具體屬性如下表:

direction Axis.vertical表示垂直方向,Axis.horizontal表示水準方向
flex 彈性系數,大于0會按比例來分割,等于0不會擴充占用的空間

可以把它了解為android:layout_weight屬性,使用代碼如下:

return Scaffold(
      appBar: AppBar(title: Text("Flex布局玩法"),),
      body: Column(
        children: <Widget>[
          Container(
            height: 400.0,
            child: Flex(
              direction: Axis.vertical,
              children: <Widget>[
                Expanded(
                  flex: 1,
                  child: Container(
                    color: Colors.red,
                  ),
                ),
                Expanded(
                  flex: 2,
                  child: Container(
                    color: Colors.yellow,
                  ),
                ),
              ],
            ),
          ),
          Container(
            height: 120.0,
            child: new Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: <Widget>[
                Expanded(
                  flex: 2,
                  child: Container(
                   color: Colors.blueAccent,
                  ),
                ),
                Expanded(
                  flex: 1,
                  child: Container(
                    color: Colors.red,
                  ),
                ),
              ],
            ),
          ),
        ],
      ),
    );
           

return Scaffold(
      appBar: AppBar(title: Text("Wrap元件玩法"),),
      body: Wrap(
        spacing: 4.0,
        runSpacing: 4.0,
        children: <Widget>[
          Container(
            color: Colors.yellow,
            child: Text("Python程式設計指南",style: new TextStyle(color: Colors.lightBlue),),
          ),
          Container(
            color: Colors.yellow,
            child: Text("Android程式設計指南",style: new TextStyle(color: Colors.lightBlue),)
          ),
          Container(
              color: Colors.yellow,
              child: Text("Flutter",style: new TextStyle(color: Colors.lightBlue),)
          ),
          Container(
              color: Colors.yellow,
              child: Text("VUE",style: new TextStyle(color: Colors.lightBlue),)
          ),
          Container(
              color: Colors.yellow,
              child: Text("Scaffold",style: new TextStyle(color: Colors.lightBlue),)
          ),
          Container(
              color: Colors.yellow,
              child: Text("Container",style: new TextStyle(color: Colors.lightBlue),)
          ),
          Container(
              color: Colors.yellow,
              child: Text("Colors",style: new TextStyle(color: Colors.lightBlue),)
          ),
          Container(
              color: Colors.yellow,
              child: Text("Colors.yellow",style: new TextStyle(color: Colors.lightBlue),)
          ),
        ],
      ),
    );