flutter学习之Listview

Posted 隔壁小王66

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flutter学习之Listview相关的知识,希望对你有一定的参考价值。

ListView构造方法

ListView.separated(
    Key key,
    Axis scrollDirection = Axis.vertical,
    bool reverse = false,
    ScrollController controller,
    bool primary,
    ScrollPhysics physics,
    bool shrinkWrap = false,
    EdgeInsetsGeometry padding,
    @required IndexedWidgetBuilder itemBuilder,
    @required IndexedWidgetBuilder separatorBuilder,
    @required int itemCount,
    bool addAutomaticKeepAlives = true,
    bool addRepaintBoundaries = true,
    bool addSemanticIndexes = true,
    double cacheExtent,
  )
scrollDirection滑动方向
reverse是否按照阅读方向相反的方向滑动
controller此属性接受一个ScrollController对象。ScrollController的主要作用是控制滚动位置和监听滚动事件
primary指是否使用widget树中默认的PrimaryScrollController;当滑动方向为垂直方向(scrollDirection值为Axis.vertical)并且没有指定controller时,primary默认为true.
physics此属性接受一个ScrollPhysics类型的对象,它决定可滚动组件如何响应用户操作
shrinkWrap该属性表示是否根据子组件的总长度来设置ListView的长度,默认值为false
padding内边距
itemBuilder构建item widget
separatorBuilder构建分割线 widget
itemCountitem 的数据长度
addAutomaticKeepAlives默认true,该属性表示是否将列表项(子组件)包裹在AutomaticKeepAlive 组件中,如果将列表项包裹在AutomaticKeepAlive中,在该列表项滑出视口时它也不会被GC(垃圾回收),它会使用KeepAliveNotification来保存其状态。如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。
addRepaintBoundaries默认true,该属性表示是否将列表项(子组件)包裹在RepaintBoundary组件中。当可滚动组件滚动时,将列表项包裹在RepaintBoundary中可以避免列表项重绘,但是当列表项重绘的开销非常小(如一个颜色块,或者一个较短的文本)时,不添加RepaintBoundary反而会更高效。
itemExtent滚动方向是垂直方向,则itemExtent代表子组件的高度;如果滚动方向为水平方向,则itemExtent就代表子组件的宽度。

一般来说,默认参数大多数情况下不需要改动

默认构造方法

默认构造函数有一个children参数,它接受一个Widget列表(List)。这种方式适合只有少量的子组件的情况

ListView(
          scrollDirection: Axis.vertical,
          shrinkWrap: true,
          children: <Widget>[
            Container(
              color: Colors.red,
              child: Text("春眠不觉晓"),
            ),
            Text("处处闻啼鸟"),
            Text("夜来风雨声"),
            Text("花落知多少"),
          ],
        ),

ListView.builder

ListView.builder适合列表项比较多(或者无限)的情况,因为只有当子组件真正显示的时候才会被创建,也就说通过该构造函数创建的ListView是支持基于Sliver的懒加载模型的。

class List2 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    return ListView.builder(
      itemBuilder: (BuildContext context, int index) 
        return ListTile(
          title: Text("标题"),
          subtitle: Text("副标题"),
          leading: Icon(Icons.add_a_photo),
          trailing: Text("2222"),
        );
      ,
      scrollDirection: Axis.vertical,
      itemExtent: 50,
      itemCount: 50,
    );
  

ListView.separated

ListView.separated可以在生成的列表项之间添加一个分割组件,它比ListView.builder多了一个separatorBuilder参数,该参数是一个分割组件生成器。

class List3 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    return ListView.separated(
      itemBuilder: (BuildContext context, int index) 
        return ListTile(
          title: Text("标题"),
          subtitle: Text("副标题"),
          leading: Icon(Icons.add_a_photo),
          trailing: Text("2222"),
        );
      ,
      separatorBuilder: (BuildContext context, int index) 
        return Divider(
          indent: 10,
          endIndent: 10,
          color: Colors.grey,
        );
      ,
      itemCount: 50,
    );
  


Divider 分割线

indent起点缩进距离
endIndent终点缩进距离
color分割线的颜色
height分割线区域的高度,并非分割线的高度
thickness分割线的厚度,真正的分割线的高度

实现分割线样式

可以通过逻辑运算,用分割线来实现分组标题

class List4 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    Widget divider = Container(
      color: Colors.blue,
      alignment: Alignment.center,
      padding: EdgeInsets.all(8),
      child: Text(
        "这是标题",
        style: TextStyle(fontSize: 24,color: Colors.white),
      ),
    );
    return ListView.separated(
      itemBuilder: (BuildContext context, int index) 
        return ListTile(
          title: Text("标题"),
          subtitle: Text("副标题"),
          leading: Icon(Icons.add_a_photo),
          trailing: Text("$index"),
        );
      ,
      separatorBuilder: (BuildContext context, int index) 
        return index > 0 && index % 6 == 0
            ? divider
            : Divider(
                color: Colors.grey,
              );
      ,
      itemCount: 50,
    );
  


ListView item点击事件,item内部点击事件的实现

item的点击事件用手势widget,GestureDetector来实现,item内部点击事件用监听GestureDetector或者button的onpress()

class List5 extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    Widget divider = Container(
      color: Colors.blue,
      alignment: Alignment.center,
      padding: EdgeInsets.all(8),
      child: Text(
        "这是标题",
        style: TextStyle(fontSize: 24, color: Colors.white),
      ),
    );

    return ListView.separated(
      itemBuilder: (BuildContext context, int index) 
        return GestureDetector(
          child: ListTile(
            title: Text("标题"),
            subtitle: Text("副标题"),
            leading: Icon(Icons.add_a_photo),
            trailing: IconButton(
              icon: Icon(Icons.arrow_forward_ios),
              onPressed: () 
                print("点击了返回按钮$index");
              ,
            ),
          ),
          onTap: () 
            print("点击了$index");
          ,
        );
      ,
      separatorBuilder: (BuildContext context, int index) 
        return index > 0 && index % 6 == 0
            ? divider
            : Divider(
                color: Colors.grey,
              );
      ,
      itemCount: 50,
    );
  


demo

class List6 extends StatelessWidget 
  Widget divider = Container(
    color: Colors.blue,
    padding: EdgeInsets.all(8),
    child: Text(
      "这是标题",
      style: TextStyle(fontSize: 24, color: Colors.white),
    ),
  );

  Widget item = Container(
      margin: EdgeInsets.all(20),
      child: DecoratedBox(
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(6),
          border: Border.all(color: Colors.grey, width: 1),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            ClipRRect(
              borderRadius: BorderRadius.all(Radius.circular(6)),
              child: Image.network(
                "https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1574328399499&di=7ff1a40b7f76750091472b47e70d0a09&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201312%2F17%2F20131217205040_d5taC.jpeg",
              ),
            ),
            Padding(
              padding: EdgeInsets.all(20),
              child: Text("标题",style: TextStyle(
                fontSize: 24,
              ),),
            ),
            Padding(
              padding: EdgeInsets.fromLTRB(20,0,0,20),
              child: Text("这是一个副标题"),
            ),
          ],
        ),
      ));

  @override
  Widget build(BuildContext context) 
    // TODO: implement build

    return ListView.separated(
      itemBuilder: (BuildContext context, int index) 
        return GestureDetector(
          child: item,
          onTap: () 
            print("点击了$index");
          ,
        );
      ,
      separatorBuilder: (BuildContext context, int index) 
        return index > 0 && index % 6 == 0
            ? divider
            : Divider(
                color: Colors.grey,
              );
      ,
      itemCount: 50,
    );
  


以上是关于flutter学习之Listview的主要内容,如果未能解决你的问题,请参考以下文章

Flutter:ListView最大高度

Flutter中ListView无法显示的问题

带有滚动条的 Flutter Listview

Android Material Design学习之RecyclerView代替 ListView

Flutter学习之混合开发

Flutter学习之混合开发