美文网首页FlutterDevSupport
Flutter基础组件(3-1)-ListView(ListVi

Flutter基础组件(3-1)-ListView(ListVi

作者: 周灬 | 来源:发表于2019-11-28 15:15 被阅读0次

    在我们开发App的时,最常用的就是列表,在flutter中使用ListView来实现类表的功能.

    1.ListView使用方法

    1.1 ListView()

    ListView的创建方法是直接调用其默认的构造函数来创建列表.
    下面我们就来看下其构造函数:

    ListView({
        Key key,
        Axis scrollDirection = Axis.vertical,
        bool reverse = false,
        ScrollController controller,
        bool primary,
        ScrollPhysics physics,
        bool shrinkWrap = false,
        EdgeInsetsGeometry padding,
        this.itemExtent,
        bool addAutomaticKeepAlives = true,
        bool addRepaintBoundaries = true,
        bool addSemanticIndexes = true,
        double cacheExtent,
        List<Widget> children = const <Widget>[],
        int semanticChildCount,
        DragStartBehavior dragStartBehavior = DragStartBehavior.down,
      })
    
    • key:做一个标志来使用,相当于iOS中的tag;
    • scrollDirection:列表的滚动方向,可选值有Axis的horizontal和vertical,可以看到默认是垂直方向上滚动;
    • reverse:是一个bool值,选择是否翻转;
    • controller:控制器,处理与列表滚动相关的,比如监听列表的滚动的事件,滚动的位置;
    • physics: 列表滚动至边缘后继续拖动的物理效果,Android与iOS效果不同。Android会呈现出一个波纹状(对应ClampingScrollPhysics),而iOS上有一个回弹的弹性效果(对应BouncingScrollPhysics)。如果你想不同的平台上呈现各自的效果可以使用AlwaysScrollableScrollPhysics,它会根据不同平台自动选用各自的物理效果。如果你想禁用在边缘的拖动效果,那可以使用NeverScrollableScrollPhysics;
    • shrinkWrap: 该属性将决定列表的长度是否仅包裹其内容的长度。当ListView嵌在一个无限长的容器组件中时,shrinkWrap必须为true,否则Flutter会给出警告;
    • padding: 列表内边距;
    • itemExtent: 子元素长度。当列表中的每一项长度是固定的情况下可以指定该值,有助于提高列表的性能(因为它可以帮助ListView在未实际渲染子元素之前就计算出每一项元素的位置);
    • cacheExtent: 预渲染区域长度,ListView会在其可视区域的两边留一个cacheExtent长度的区域作为预渲染区域(对于ListView.build或ListView.separated构造函数创建的列表,不在可视区域和预渲染区域内的子元素不会被创建或会被销毁);
    • children: 容纳子元素的组件数组;

    默认的创建模式:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
    
      Widget _getListItem(String title,IconData icon){
        return Container(
          child: ListTile(
            leading: Icon(icon),
            trailing: Icon(icon),
            title: Text(title),
            subtitle: Text('我是将军'),
          ),
        );
      }
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'textTitle',
          home: Scaffold(
            appBar: AppBar(
              title: Text('最后战役'),
            ),
            body: Center(
              child: ListView(
                children: <Widget>[
                  _getListItem('第一行', Icons.map),
                  _getListItem('第二行', Icons.phone),
                  _getListItem('第三行', Icons.adb),
                ],
              ),
            ),
          ),
        );
      }
    }
    

    1.2 ListTitle()

    在上面的代码部分出现了一个ListTitle,ListTile 是Flutter 给我们准备好的widget 提供非常常见的构造和定义方式,包括文字,icon,点击事件,一般是能够满足基本需求,但是就不能自己定义了.

    ListTitle的属性
    this.leading,              // item 前置图标
    this.title,                // item 标题
    this.subtitle,             // item 副标题
    this.trailing,             // item 后置图标
    this.isThreeLine = false,  // item 是否三行显示
    this.dense,                // item 直观感受是整体大小
    this.contentPadding,       // item 内容内边距
    this.enabled = true,
    this.onTap,                // item onTap 点击事件
    this.onLongPress,          // item onLongPress 长按事件
    this.selected = false,     // item 是否选中状态
    
    1.1的效果图.png

    1.3 ListView builder()

    builder 顾名思义 构造 可以非常方便的构建我们自己定义的child布局,所以在Flutter中非常的常用。

    builder属性详细介绍
    //设置滑动方向 Axis.horizontal 水平  默认 Axis.vertical 垂直
    scrollDirection: Axis.vertical,
    //内间距EdgeInsets.all(),EdgeInsets.only().
    padding: EdgeInsets.all(10.0),
    //是否倒序显示 默认正序 false  倒序true
    reverse: false,
    //false,如果内容不足,则用户无法滚动 而如果[primary]为true,它们总是可以尝试滚动。
    primary: true,
    //确定每一个item的高度 会让item加载更加高效
    itemExtent: 50.0,
    //内容适配
    shrinkWrap: true,
    //item 数量
    itemCount: list.length,
    //滑动类型设置
    physics: new ClampingScrollPhysics(),
    //cacheExtent  设置预加载的区域 
    cacheExtent: 30.0, 
    //滑动监听
    controller ,
    
    • child 高度会适配 item填充的内容的高度,我们非常的不希望child的高度固定,因为这样的话,如果里面的内容超出就会造成布局的溢出。
    • shrinkWrap多用于嵌套listView中 内容大小不确定 比如 垂直布局中 先后放入文字 listView (需要Expend包裹否则无法显示无穷大高度 但是需要确定listview高度 shrinkWrap使用内容适配不会有这样的影响).
    • primary在构造中默认是false 它的意思就是为主的意思,primary为true时,我们的controller 滑动监听就不能使用了.
    • physics这个属性几个滑动的选择:
      AlwaysScrollableScrollPhysics() 总是可以滑动
      NeverScrollableScrollPhysics禁止滚动
      BouncingScrollPhysics 内容超过一屏 上拉有回弹效果
      ClampingScrollPhysics 包裹内容 不会有回弹
    • cacheExtent这个属性的意思就是预加载的区域,设置预加载的区域 cacheExtent 强制设置为了 0.0,从而关闭了“预加载”.
    • controller滑动监听,我们多用于上拉加载更多,通过监听滑动的距离来执行操作。
    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'textTitle',
          home: Scaffold(
            appBar: AppBar(
              title: Text('最后战役'),
            ),
            body: Container(
              child:listViewLayoutBuilder(),
            ),
          ),
        );
      }
    }
    ///listView builder 构建
    Widget listViewLayoutBuilder() {
      return ListView.builder(
          scrollDirection: Axis.vertical,
          padding: EdgeInsets.all(10.0),
          reverse: false,
          primary: true,
          itemExtent: 50.0,
          shrinkWrap: true,
          itemCount: 4,
          cacheExtent: 30.0,
          physics: new ClampingScrollPhysics(),
        itemBuilder: (context, i){
        return Container(
          child: new Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: <Widget>[
              new Text(
                "1",
                style: new TextStyle(fontSize: 18.0, color: Colors.red),
              ),
              new Text(
                "2",
                style: new TextStyle(fontSize: 18.0, color: Colors.green),
              ),
              new Text(
                "3",
                style: new TextStyle(fontSize: 18.0, color: Colors.blue),
              ),
            ],
          ),
        );}
      );
    }
    

    2.ListView的分割线加入

    2.1 builder模式来设置分割线

    我们在正常的需求中大部分是需要item的分割线的,而在builder模式中使用divide 会有种情况(divide放在item的布局中 通过Column),我们会发现divide并没有直接延时到item两端而是会有左右padding。
    所以我们可以通过另外一种方式去实现。

    //1.扩大list容积 为什么是两倍,因为我们给了divide的index
     Widget listView = new ListView.builder(
                  itemCount: list.length * 2 ,
                  itemBuilder: (context, index) => itemDividerRow(context, index));
    //2. 根据下标分配item类型
    itemDividerRow(context, int i) {
      if (i.isOdd) {//是奇数
            return new Divider( //返回分割线
              height: 1.0,
            );
      } else {
            i = i ~/ 2;
            return getRowWidget(context, orderList[i]);  //返回item 布局
     }
    } 
    

    这样我们就可以去实现了,builder模式分割线 .

    2.2 ListView separated

    ListView.separated的模式更加方便我们给列表页面添加分割线.

    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,
      })
    

    从属性大部分可以看出和flutter的ListView属性差不多.比ListView多了一个separatorBuilder的属性.

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'textTitle',
          home: Scaffold(
            appBar: AppBar(
              title: Text('最后战役'),
            ),
            body: Container(
            child: ListViewBuilder(),
            ),
          ),
        );
      }
    }
    
    class ListViewBuilder extends StatefulWidget {
      @override
      State<StatefulWidget> createState() {
        return _ListViewBuilder();
      }
    }
    
    class _ListViewBuilder extends State<ListViewBuilder> {
      /*初始项为50个*/
      List<int> indexs = List.generate(50, (index) {
        return index;
      });
    
      @override
      Widget build(BuildContext context) {
        /*灰色分割线*/
        var divider = Divider(
          color: Colors.grey,
        );
    
        return ListView.separated(
            padding: EdgeInsets.all(10),
            itemCount: indexs.length,
            separatorBuilder: (context, index) {
              return divider;
            },
            itemBuilder: (context, index) {
              /*加载到底部时且集合数量小于100的话,获取更多数据*/
              if (index == indexs.length - 1 && indexs.length < 100) {
                _getMoreData(index);
              }
    
              return Text("${index}");
            });
      }
    
      void _getMoreData(int index) {
        Future.delayed(Duration(milliseconds: 300)).then((e) {
          setState(() {
            /*往集合里添加10条数据*/
            indexs.addAll(List.generate(10, (i) {
              return index + i;
            }));
          });
        });
      }
    }
    
                                想了解更多Flutter学习知识请联系:QQ(814299221)
    

    相关文章

      网友评论

        本文标题:Flutter基础组件(3-1)-ListView(ListVi

        本文链接:https://www.haomeiwen.com/subject/dwybictx.html