flutter學習--列表組件

flutter中常用的列表組件爲ListView、GridView和SliverList,本文將3種組件實現步驟和多種實現方式做個講解。

一、ListView

能夠實現靜態加載和動態加載。所謂的靜態加載就是需要設置好Listview所加載的子view,數量已定。所謂的動態加載就是子view數量不定。

1、靜態加載

(1)源碼屬性:
在這裏插入圖片描述
有幾個比較重要的屬性:

  • scrollDirection:滾動方向
  • itemExtent :決定子view的高度或寬度。
  • children :子view。

(2)使用:

class ListViewWidget1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('ListViewWidget1'),
      ),
      body: ListView(
        scrollDirection: Axis.vertical,
        itemExtent: 80, //限制每一項的高度或寬度,即使子view設置了高度。
        children: <Widget>[
          Container(
            height: 50,
            color: Colors.red,
          ),
          Container(
            height: 50,
            color: Colors.green,
          ),
          Container(
            height: 50,
            color: Colors.blue,
          ),
        ],
      ),
    );
  }
}

在children中給指定要加載的子view。注意這裏即使設置了子view的高度爲50,由於itemExtent設置爲80。所以子view的高度爲80。

2、動態加載–ListView.builder

(1)源碼屬性:
在這裏插入圖片描述
有幾個比較重要的屬性:

  • itemBuilder:用於加載子view
  • itemCount:限制子view的個數。

(2)使用:

class ListViewWidget2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('ListViewWidget2'),
      ),
      body: ListView.builder(
        reverse: true,
        itemBuilder: (context, index) {//index爲子view下標。
          return index % 2 == 0
              ? Container(
                  height: 50,
                  color: Colors.red,
                )
              : Container(
                  height: 50,
                  color: Colors.green,
                );
        },
        itemCount: 100, //顯示條目數量,不指定顯示無限數量
        itemExtent: 30,
      ),
    );
  }
}

現象就是兩個色塊交替顯示,總共100條。

3、動態加載–ListView.separated

(1)源碼屬性:
在這裏插入圖片描述
有幾個比較重要的屬性:

  • itemBuilder:用於加載子view
  • itemCount:限制子view的個數。
  • separatorBuilder:用於加載分割每個子view間的分割線。

(2)使用:

class ListViewWidget3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
        appBar: AppBar(
          title: Text('ListViewWidget2'),
        ),
        body: ListView.separated(
            itemBuilder: (context, index) {
              //item
              return index % 2 == 0
                  ? Container(
                      height: 50,
                      color: Colors.red,
                    )
                  : Container(
                      height: 50,
                      color: Colors.green,
                    );
            },
            separatorBuilder: (context, index) {
              //分割線
              return Divider(
                height: 5,
                color: Colors.black,
                thickness: 5,
              );
            },
            itemCount: 100));
  }
}

現象就是兩個色塊交替顯示,總共100條。每個子view之間有5px的黑色分割線。

4、動態加載–實現ListView分頁加載

(1)先上代碼吧,後面詳解:

class ListViewWidget4 extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return ListViewWidget4State();
  }
}

class ListViewWidget4State extends State<ListViewWidget4> {
  List<String> _datas = <String>[''];

  //初始化數據
  void _initData() {
    //模擬網絡加載,每次生成20條數據
    Future.delayed(Duration(milliseconds: 100), () {
      _datas.insertAll(_datas.length - 1,
          generateWordPairs().take(20).map((e) => e.asPascalCase).toList());
          //刷新數據
      setState(() {});
    });
  }

  @override
  void initState() {
    super.initState();
	//初始化數據
    _initData();
  }

  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(title: Text('分頁listView')),
      body: ListView.builder(
        itemBuilder: (context, index) {
          if (_datas.length - 1 == index) {
            if (_datas.length < 100) {
              //最多加載100條
              _initData();
              return Container(
                width: 10,
                height: 10,
                child: CircularProgressIndicator(),
              );
            } else {
              return Center(
                  child: Container(
                height: 20,
                color: Colors.red,
                child: Text(
                  ('沒有更多數據了'),
                ),
              ));
            }
          }
          return ListTile(
            //數據顯示
            title: Text(_datas[index]),
          );
        },
        itemCount: _datas.length, //列表長度
      ),
    );
  }
}

由於我們需要刷新動態刷新列表數據的,所以這裏使用StatefulWidget。通過_initData()方法來模擬網絡加載,每次加載20條,通過第三方隨機生成20個字符串。itemBuilder中限制最多加載100條,並且不足100條,每次下拉到最後一項都會再次生成20個字符串。

(2)效果:
在這裏插入圖片描述

二、GridView

1、靜態加載–GridView

(1)源碼屬性:
在這裏插入圖片描述
有幾個比較重要的屬性:

  • gridDelegate:用於控制每一行或每一列顯示的子view個數,以及子view間距
  • children : 子view列表

(2)使用:

class GridViewWidget1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('GridViewWidget1'),
      ),
      body: GridView(
        padding: EdgeInsets.all(10), //外邊距
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3, //控制每一行顯示的個數,子view的寬度自動計算
            mainAxisSpacing: 5, //主軸方向的child間距
            crossAxisSpacing: 5, //垂直軸方向的child間距
            childAspectRatio: 2 //控制寬高比,此時表示高度爲寬度的一半
            ),
        children: <Widget>[
          Container(
            color: Colors.red,
          ),
          Container(
            color: Colors.green,
          ),
          Container(
            color: Colors.blue,
          ),
          Container(
            color: Colors.blue,
          ),
          Container(
            color: Colors.red,
          ),
          Container(
            color: Colors.green,
          ),
        ],
      ),
    );
  }
}

現象就是每一行顯示3個色塊,總共顯示2行,子view之間橫向和縱向間距爲5,注意 childAspectRatio 控制子view的顯示寬高比。

2、靜態加載–GridView.count

這種方式能夠實現和上述方式一樣的效果。
(1)源碼屬性:
在這裏插入圖片描述
注意這裏的幾個屬性mainAxisSpacing、crossAxisSpacing、childAspectRatio就是之前方式gridDelegate的屬性。
(2)使用:

class GridViewWidget2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('GridViewWidget3'),
      ),
      body: GridView.count(
        crossAxisCount: 3,
        mainAxisSpacing: 5,
        //主軸方向的child間距
        crossAxisSpacing: 5,
        //垂直軸方向的child間距
        childAspectRatio: 2,
        //子view
        children: <Widget>[
          Container(
            color: Colors.red,
          ),
          Container(
            color: Colors.green,
          ),
          Container(
            color: Colors.blue,
          ),
          Container(
            color: Colors.blue,
          ),
          Container(
            color: Colors.red,
          ),
          Container(
            color: Colors.green,
          ),
        ],
      ),
    );
  }
}
3、靜態加載–GridView.extent

可以實現不指定每一行或每一列顯示的個數,自動適配個數。
(1)源碼屬性:
在這裏插入圖片描述
重要屬性:

  • maxCrossAxisExtent:控制每一行顯示多少個子view
    (2)使用:
class GridViewWidget4 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      appBar: AppBar(
        title: Text('GridViewWidget4'),
      ),
      body:
          GridView.extent(maxCrossAxisExtent: 100, //指定每個子view的最大寬度,顯示個數根據屏幕寬度而定

              children: <Widget>[
            Container(
              color: Colors.red,
            ),
            Container(
              color: Colors.green,
            ),
            Container(
              color: Colors.blue,
            ),
            Container(
              color: Colors.pink,
            ),
            Container(
              color: Colors.black,
            ),
            Container(
              color: Colors.yellow,
            ),
          ]),
    );
  }
}
4、動態加載–GridView.builder

(1)源碼屬性:
在這裏插入圖片描述
重要屬性:

  • gridDelegate:用於控制每一行或每一列顯示的子view個數,以及子view間距
  • itemBuilder:動態加載每一個子view
  • itemCount:指定顯示子view的個數

(2)使用:

class GridViewWidget3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
        appBar: AppBar(
          title: Text('GridViewWidget3'),
        ),
        body: GridView.builder(
            itemCount: 11, //子view顯示的個數
            gridDelegate: //設置每一行顯示3個
                SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 3),
            itemBuilder: (context, index) {
              //加載每一個子view
              return index % 2 == 0
                  ? Container(
                      color: Colors.red,
                    )
                  : Container(
                      color: Colors.blue,
                    );
            }));
  }
}

三、SliverList–SliverFixedExtentList

這裏只講解SliverFixedExtentList。我們用它配合 SliverAppBar 實現android中 CollapsingToolbarLayout 的效果。
(1)使用:

class SliverListWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return Scaffold(
      body: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            title: Text('SliverAppBar'),
            backgroundColor: Colors.pinkAccent,
            expandedHeight: 200,
            floating: true,//floating 和snap同時設置爲true,下拉會like顯示flexibleSpace內容。
            snap: true,
            pinned: true,//appBar不會消失,一直在標題欄
            flexibleSpace: FlexibleSpaceBar(//圖片
              background: Image.asset(
                "assets/images/lock_bg.png",
                fit: BoxFit.cover,
              ),
            ),
          ),
          SliverFixedExtentList(//子view展示
              itemExtent: 150,
              delegate: SliverChildListDelegate.fixed([
                Container(
                  color: Colors.red,
                ),
                Container(
                  color: Colors.green,
                ),
                Container(
                  color: Colors.blue,
                ),
                Container(
                  color: Colors.pink,
                ),
                Container(
                  color: Colors.black,
                ),
                Container(
                  color: Colors.yellow,
                ),
              ]))
        ],
      ),
    );
  }
}

(2)效果:
在這裏插入圖片描述

發佈了76 篇原創文章 · 獲贊 9 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章