专栏首页阿策小和尚【Flutter 专题】12 ListView 用哪种方式绑定数据?

【Flutter 专题】12 ListView 用哪种方式绑定数据?

和尚昨天刚学习了一下底部状态栏 BottomNavigationBar 的基本使用方法,今天学习一下 ListView 的基本用法。 和尚觉得 **Flutter ** 中 ListView 这个控件很强大,它兼顾了 Android 中的 ScrollView 和 ListView 两个控件的效果,既可以当列表用也可以充当可滑动布局。和尚今天主要测试作为普通列表时的基本用法。

列表 item -> ListTile

Flutter 很贴心的提供了一种常见的列表 item 样式,可以包括前后图标以及大小标题的样式;和尚特意了解了一下 ListTile 的基本属性,如下:

const ListTile({
    Key key,
    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 是否选中状态
})

Tips: 和尚对 dense 属性理解不是很好,直观的感觉是 dense 为 true 时整体会小一些,文字更为明显,就像整体分辨率变高;如下图:

列表 -> ListView

Flutter 中 ListView 用法与 Android 中类似,首先添加数据,之后绑定列表;Flutter 中绑定列表有四种方式,分别是 默认 List / ListView.builder / ListView.separated / ListView.custom;和尚主要对前三种方式逐一测试;如图:

无论是用那种绑定数据的方式首先第一步都要添加数据,和尚测试基本样式包括 item 前置图标(leading)、标题文字(title)、后置图标(trailing),并设置了基本的 onTap() 方法;如下:

dense 为 true

dense 为 false

List<String> strItems = <String>[
    '图标 -> keyboard', '图标 -> print',
    '图标 -> router', '图标 -> pages',
    '图标 -> zoom_out_map', '图标 -> zoom_out',
    '图标 -> youtube_searched_for', '图标 -> wifi_tethering',
    '图标 -> wifi_lock', '图标 -> widgets',
    '图标 -> weekend', '图标 -> web',
    '图标 -> accessible', '图标 -> ac_unit',
];

List<Icon> iconItems = <Icon>[
    new Icon(Icons.keyboard), new Icon(Icons.print),
    new Icon(Icons.router), new Icon(Icons.pages),
    new Icon(Icons.zoom_out_map), new Icon(Icons.zoom_out),
    new Icon(Icons.youtube_searched_for), new Icon(Icons.wifi_tethering),
    new Icon(Icons.wifi_lock), new Icon(Icons.widgets),
    new Icon(Icons.weekend), new Icon(Icons.web),
    new Icon(Icons.accessible), new Icon(Icons.ac_unit),
];

Widget buildListData(BuildContext context, String strItem, Icon iconItem) {
    return new ListTile(
      isThreeLine: false,
      leading: iconItem,
      title: new Text(strItem),
      trailing: new Icon(Icons.keyboard_arrow_right),
      onTap: () {
        showDialog(
          context: context,
          builder: (BuildContext context) {
            return new AlertDialog(
              title: new Text(
                'ListViewDemo',
                style: new TextStyle(
                  color: Colors.black54,
                  fontSize: 18.0,
                ),
              ),
              content: new Text('您选择的item内容为:$strItem'),
            );
          },
        );
      },
    );
}

1. 默认 List

和尚理解默认 List 方式,是把数据 Iterable 添加到列表中,之后直接添加到 ListView 即可;如下:

List<Widget> _list = new List();
for (int i = 0; i < strItems.length; i++) {
    _list.add(buildListData(context, strItems[i], iconItems[i]));
}
// 添加分割线
var divideList =
        ListTile.divideTiles(context: context, tiles: _list).toList();
body: new Scrollbar(
    child: new ListView(
        // 添加ListView控件
//        children: _list,    // 无分割线
        children: divideList, // 添加分割线
    ),
);

Tips: 如果需要设置分割线,需要对列表 item 添加处理,ListTile.divideTiles

2. ListView.builder

和尚理解 builder 方式很像对话框类型逐个添加需要的属性;需要在 builder 中添加列表数据;而添加分割线的方式更让和尚体会到 Flutter 一切都是 widget 思想的重要性,如下:

// 没有分割线
child: new ListView.builder(
    itemCount: iconItems.length,  // 数据长度
    itemBuilder: (context, item) {
        return buildListData(context, strItems[item], iconItems[item]);
    },
),

// 添加分割线
child: new ListView.builder(
    itemCount: iconItems.length,
    itemBuilder: (context, item) {
        return new Container(
            child: new Column(
              children: <Widget>[
                buildListData(context, strItems[item], iconItems[item]),
                new Divider()
              ],
            ),
        );
    },
),

3. ListView.separated

和尚对 separated 方式最大的理解是有直接的分隔符设置方式,对分隔符列表应用更实用;设置 separatorBuilder 属性即可;如下:

child: new ListView.separated(
    itemCount: iconItems.length,
    separatorBuilder: (BuildContext context, int index) => new Divider(),  // 添加分割线
    itemBuilder: (context, item) {
        return buildListData(context, strItems[item], iconItems[item]);
    },
),

4. ListView.custom

和尚暂时不对本加载方式做实例尝试,和尚理解 ListView.custom 更适合对 item 中含有子类 item,并对子类 item 的显隐性有更多操作时使用该方式更好;在以后的尝试中和尚会单独对这种方式进行测试整理。

主要源码

List<Widget> _list = new List();

@override
Widget build(BuildContext context) {
    for (int i = 0; i < strItems.length; i++) {
      _list.add(buildListData(context, strItems[i], iconItems[i]));
    }
    var divideList =
        ListTile.divideTiles(context: context, tiles: _list).toList();
    return new Scaffold(
      body: new Scrollbar(
        // 默认方式 List
//        child: new ListView(
//          children: divideList, //添加ListView控件
//        ),
        // ListView.separated 方式
//        child: new ListView.separated(
//          itemCount: iconItems.length,
//          separatorBuilder: (BuildContext context, int index) => new Divider(),
//          itemBuilder: (context, item) {
//            return buildListData(context, strItems[item], iconItems[item]);
//          },
//        ),
        // ListView.builder 方式
        child: new ListView.builder(
          itemCount: iconItems.length,
          itemBuilder: (context, item) {
            return new Container(
              child: new Column(
                children: <Widget>[
                  buildListData(context, strItems[item], iconItems[item]),
                  new Divider()
                ],
              ),
            );
          },
        ),
//        child: new ListView.custom(
//
//        ),
      ),
    );
}

Tips: 列表中有一个属性很有意思:reverse 是否反转,如果设为 true,列表默认滑倒底部而且数据也是倒叙排列;若设为 false,则一切正常。其他很多属性也很有特点,和尚还没来得及深入探究。

GitHub Demo


和尚刚接触 Flutter 时间不长,还有很多不清楚和不理解的地方,如果又不对的地方还希望多多指出。

本文分享自微信公众号 - 阿策小和尚(gh_8297e718c166),作者:阿策小和尚

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2018-08-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Flutter 16】图解 ListView 异步加载数据与 Loading 等待

    和尚前两天再学 ListView 时,整理了一下在列表中展示多种不同 item 样式,今天继续深入学习异步请求数据并加载新闻列表以及初始进入页面的 ...

    阿策
  • 【Flutter 专题】08 小小优化【登录】页面

    和尚前两天花了很久才搭建了一个最简单的【登录】页面,但依然还有很多需要优化的地方,和尚又花了很久的时间尝试做了一点点的优化,仅针对优化的部分简单整理...

    阿策
  • 【Flutter 专题】07 您搭好【登录】页面了么?

    和尚最近在利用业余时间学习 Flutter,还真的是值得研究。和尚觉得学习一门技术最好的方式就是动手,在实践过程中结合官网文档才能更快的学习和理解。...

    阿策
  • SwiftUI,是FlutterUI该有的样子吗?

    刚刚的【2019 WWDC 大会】苹果发布了 SwiftUI 开发语言,咋看上去,和Flutter的UI比较像,但个人感觉比Flutter的方式更好——虽然有些...

    IT晴天
  • Spark——底层操作RDD,基于内存处理数据的计算引擎

    Apache Spark是一个快速的通用集群计算框架 / 殷勤。它提供Java,Scala,Python和R中的高级API,以及支持常规执行图的优化引擎。它还支...

    时间静止不是简史
  • 程序员必看:实现栈有这两种策略,有完整分析和代码实现

    这两篇中分别总结了程序的时间性能度量指标,典型的时间复杂度类型,Java中类型的空间消耗的量化情况。后一篇考虑计算机中最重要的基础算法查找和排序算法,这篇可以说...

    double
  • Android网络编程(二)HttpClient与HttpURLConnection

    相关文章 Android网络编程(一)HTTP协议原理 前言 上一篇我们了解了HTTP协议原理,这一篇我们来讲讲Apache的HttpClient和Java的...

    用户1269200
  • java基础第十四篇之Map

    一,Map集合的特点: * * 1.Map集合和Collection集合,没有关系 * * 2.Map集合的元素是成对存在(夫妻关系)...

    海仔
  • java:Set,Map排序输出到Writer

    一般来说java.util.Set,java.util.Map输出的内容的顺序并不是按key的顺序排列的,但是java.util.TreeMap,java.ut...

    用户1148648
  • 【经验总结】Java在ACM算法竞赛编程中易错点

    一、Java之ACM易错点 1. 类名称必须采用public class Main方式命名 2. 在有些OJ系统上,即便是输出的末尾多了一个“ ”,程序可能会输...

    Angel_Kitty

扫码关注云+社区

领取腾讯云代金券