Flutter基础组件(3-1)-ListView(ListView的创建和加分割线)

在我们开发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)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,386评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,142评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,704评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,702评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,716评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,573评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,314评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,230评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,680评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,873评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,991评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,706评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,329评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,910评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,038评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,158评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,941评论 2 355

推荐阅读更多精彩内容