关于Flutter列表ListView的那些事儿

flutter里面的listview支持竖直列表和水平列表。

水平列表
 scrollDirection: Axis.horizontal
垂直列表
scrollDirection:  Axis.vertical

listview的创建方式也多种多样。

item数量固定的

可以直接采用children赋值,直接添加子item即好。

new ListView(
  children: [
    new Container(
      width: 160.0,
      color: Colors.red,
    ),
    new Container(
      width: 160.0,
      color: Colors.blue,
    ),
    new Container(
      width: 160.0,
      color: Colors.green,
    ),
    new Container(
      width: 160.0,
      color: Colors.yellow,
    ),
    new Container(
      width: 160.0,
      color: Colors.orange,
    ),
  ],
)
子item数量是可变的

用builder方式构建。

 new ListView.builder(
      itemCount: items.length,
      itemBuilder: (context, index) {
        return Container(
          child: new Text('${items[index]}'),
        );
      },
    );

如果想给item添加分割线,可以根据index的奇偶性判断何时添加。

index.isOdd //判断是否是奇数

判断是否是奇数。

final index = i ~/ 2;//表示i除以2,但返回值是整形(向下取整),比如i为:1, 2, 3, 4, 5时,
        // 结果为0, 1, 1, 2, 2

用上面方法可以不用为divider造假数据。
另外还有一种专门添加分隔线的listview的生成方法。

ListView.separated(
      itemBuilder: (BuildContext context, int index) {
        if (index == catergoryChildList.length) {
          return buildCircleProgressBar();
        } else {
          CatergoryChild catergoryChild = catergoryChildList[index];
          return ItemView(catergoryChild, index, (index) {
            Scaffold.of(context)
                .showSnackBar(SnackBar(content: Text("第$index项被点击了")));
          });
        }
      },
      separatorBuilder: (context, index) {
        return new Divider(
          height: 1,
        );
      },
      scrollDirection: Axis.vertical,
      itemCount: catergoryChildList.length + 1,
      controller: scrollController,
    );

这种方法更加方便快捷,也不用造divider数据,有单独生成divider的地方。

listview的下拉刷新。
RefreshIndicator(
      child: listViewM,
      onRefresh: () async{
        getData();
      },
      color: Colors.blue,
    );

这样就实现了android Mateial风格的下拉刷新。
getData()方法如下:

void getData(){
    if (!isFetching) {
      catergoryChildTask.getCatergoryTask(type);
      isFetching = true;
    }
  }

需要注意的是onRefresh字段需要的是一个async的方法,如果不是async的方法会报错。
也可以这样写:

RefreshIndicator(
      child: listViewM,
      onRefresh: getData,
      color: Colors.blue,
    );

但此时getData方法是这样实现的。

  Future getData() async{
    if (!isFetching) {
      catergoryChildTask.getCatergoryTask(type);
      isFetching = true;
    }
    return null;
  }
listview的上拉加载更多

listview的上拉加载更多的触发是通过ScrollController控制的。
滚动到底部的检测条件如下:

 scrollController.addListener(() {
      if (scrollController.position.pixels ==
          scrollController.position.maxScrollExtent) {
        loadMore=true;
        getData();
      }
    });

listview最下部显示正在加载中的进度条的处理可以参考如下

 itemBuilder: (BuildContext context, int index) {
        if (index == catergoryChildList.length) {
          return buildCircleProgressBar();
        } else {
          CatergoryChild catergoryChild = catergoryChildList[index];
          return ItemView(catergoryChild, index, (index) {
            Scaffold.of(context)
                .showSnackBar(SnackBar(content: Text("第$index项被点击了")));
          });
        }
      }

其中buildCircleProgressBar的方法处理如下:

  Widget buildCircleProgressBar() {
    return Padding(
      padding: EdgeInsets.all(8),
      child: Center(child: Opacity(
          opacity: 1, child: CircularProgressIndicator()),
      ),);
  }

这样就实现了拉到最底部时显示正在加载中的子item状态。如果想要其他的处理,可以自行处理。
本文完整源代码地址:
https://github.com/happycodinggirl/flutter_gank
有什么问题,欢迎交流。

你可能感兴趣的:(关于Flutter列表ListView的那些事儿)