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)效果:
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值